【问题标题】:Efficiency of querying on views in Postgres 13在 Postgres 13 中查询视图的效率
【发布时间】:2021-07-10 16:13:22
【问题描述】:

谁能解释一下 Postgres 何时/如何处理针对视图的搜索?我对查询视图而不是表有偏见,这绝对是错误的。我不确定我的偏见是完全还是部分不合理。

潜伏在我脑海中的想法是,在某些情况下,视图缺乏来自查询的过滤条件,会生成一个大型产品,然后根据查询条件选择该产品。之后。 (我想我在 5.6 年前在 MySQL 中遇到过这样的情况,其中 MySQL 生成了一个 CROSS JOIN 来执行一些外部连接。即使结果中有两条记录可预测,它也需要几分钟才能运行。MySQL 不是 Postgres。)

我有一个使用INNER JOIN 将两个表的结果组合在一起的视图。目前,总产品约为 1.52 亿行。 Count(*) 运行需要一些时间,正如您所想象的那样。

我创建了两个存储函数来比较性能。他们都使用rcl_combined 作为RETURN 格式。

  1. rcl_combined_query 执行与rcl_combined 视图相同的select,但包含针对索引字段的where 条件。

  2. rcl_combined_query_on_view 直接搜索视图。

我在下面列出了代码。当我尝试这个时,函数执行相同的方式,并为“function_scan”生成相同的简单计划。毫秒结果,无论哪种方式。

我的偏见完全没有根据吗?或者是否存在直接查询表而不是查询 Postgres 13+ 中的视图更安全的情况(或边缘情况)?希望这不是一个不可能的问题。我们正在使用FROM(INNER) JOINLEFT JOIN,有时还使用RIGHT JOIN,它们几乎只用于小表、小表和稍大的表,但仍处于 200M 以下的行范围内。

我明白这可能是一种“视情况而定”的情况,我希望至少能澄清我在这里的一些错误假设。我不希望任何人给出确切的公式等。

-----------------------------------------------------------------
-- The view used as a result format by both of the functions, and
-- as the search target for the second query.
-----------------------------------------------------------------
CREATE OR REPLACE VIEW api.rcl_combined AS

SELECT
    record_changes_log.id,
    record_changes_log.record_id,
    record_changes_log.table_number,
    record_changes_log.updated_dts,
    record_changes_log.updated_by,
    record_changes_log.app_type,
    record_changes_log.machine_name,
    record_changes_log_detail.id AS details_id,
    record_changes_log_detail.field_name,
    record_changes_log_detail.old_value,
    record_changes_log_detail.new_value

FROM (record_changes_log
JOIN record_changes_log_detail ON ((record_changes_log.id = record_changes_log_detail.record_changes_log_id)));

-----------------------------------------------------------------
-- A function that returns the same data as the pet_pretty view
-- using the rcl_combined view format/type.
-----------------------------------------------------------------
CREATE OR REPLACE FUNCTION rcl_combined_query (record_id_in uuid)
     RETURNS  rcl_combined -- Used for the format definition and dependency tracking.

LANGUAGE sql STABLE

AS
$BODY$

-- The select, from and join recapitulate what's in the view.
SELECT
    record_changes_log.id,
    record_changes_log.record_id,
    record_changes_log.table_number,
    record_changes_log.updated_dts,
    record_changes_log.updated_by,
    record_changes_log.app_type,
    record_changes_log.machine_name,
    record_changes_log_detail.id AS details_id,
    record_changes_log_detail.field_name,
    record_changes_log_detail.old_value,
    record_changes_log_detail.new_value

FROM record_changes_log
JOIN record_changes_log_detail
  ON record_changes_log.id = record_changes_log_detail.record_changes_log_id

WHERE record_changes_log.record_id = record_id_in;

$BODY$;

-----------------------------------------------------------------
-- A function that returns the same data as the pet_pretty view
-- by searching on it.
-----------------------------------------------------------------
-- Just being thorough here, I'm very unlikely to write a function to query a view.

CREATE OR REPLACE FUNCTION rcl_combined_query_on_view (record_id_in uuid)
     RETURNS  rcl_combined -- Used for the format definition and dependency tracking.

LANGUAGE sql STABLE

AS
$BODY$

SELECT * from rcl_combined where record_id = record_id_in;

$BODY$;

【问题讨论】:

    标签: postgresql optimization view


    【解决方案1】:

    PostgreSQL 中的视图基本上就像编程语言中的宏。当您的查询引用视图以有效地将视图扩展到其定义中时,您的查询将被重写。

    因此,规划器将条件推送到您的视图中的任何问题,在“完整”写出相同的查询时也会出现。

    “物化视图”是完全不同的东西。不要把它们混在一起。它将视图查询的结果存储在基础表中,以后的查询将与此相反。您通常可以将其用于缓慢变化的摘要,例如按地区划分的每日销售总额。

    【讨论】:

    • 我很高兴我的偏见是没有根据的。我一直在试验EXPLAIN,Postgres 做了一项很棒的工作,它忽略了生成查询或视图的最终结果所不需要的连接和其他操作。现在阅读查询处理管道。这里没有物化视图。如果没有增量更新,我们还没有发现它们比完整表对我们更有用的情况。 (我们不需要归档每日快照或任何类似的东西。)
    猜你喜欢
    • 2022-06-16
    • 2020-11-19
    • 1970-01-01
    • 2012-04-29
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    相关资源
    最近更新 更多