简单的嵌套视图是不是有效(如果不包含多余的表?)

Posted

技术标签:

【中文标题】简单的嵌套视图是不是有效(如果不包含多余的表?)【英文标题】:Are simple nested views efficient (provided no superfluous tables included?)简单的嵌套视图是否有效(如果不包含多余的表?) 【发布时间】:2020-08-01 01:46:08 【问题描述】:

我一直在仔细阅读以下两个链接:

Will Postgres push down a WHERE clause into a VIEW with a Window Function (Aggregate)?

https://dba.stackexchange.com/questions/151169/are-views-harmful-for-performance-in-postgresql

以上链接中的 cmets 建议回答我的两个相关问题,但我想确保我理解。

假设我有一个观点:

create view A as
select
  x.xKey,
  x.y,
  x.z,
  y.yKey,
  y.a,
  y.b
from x
join y
  on x.xKey = y.xKey

现在我还有另一个……

create view B as
select
  A.xKey,
  A.y,
  A.z,
  A.yKey,
  A.a,
  A.b,
  r.rKey,
  r.n
from A
join r
  on A.yKey = r.yKey 

假设第三个视图 C 做更多相同的事情,但所有三个视图都是简单的选择语句。

两个问题:

    如果我使用与所涉及的任何/所有表相关的过滤器从视图 C 中进行选择,“谓词”是否总是“下推”(对我来说是新短语,希望我说得正确),以便视图 C 一样有效过滤方式与以相同方式构建的更大的独立查询一样吗?

    如果我从视图 C 中选择,但我没有利用所有连接中涉及的所有表,那么我确实付出了代价,而手工制作的选择语句可以避免连接更少的表。是吗?

非常感谢您的想法。

【问题讨论】:

查看execution plan @Wellspring 。 . .我认为任何数据库通常不会仅仅因为未使用表而优化表之间的连接。可能存在一些边缘情况——主键上的外连接——但即便如此,我还是会感到惊讶。 @GordonLinoff 我想你是说我的第二个问题很可能会在场景中付出代价? @a_horse_with_no_name 我不完全相信自己分析执行计划,因此我的问题,但这是一个很好的指导。也就是说,我不知道您的意思是答案“取决于”还是在所有此类情况下都相同。 【参考方案1】:

欢迎专家指正。

我不擅长阅读 EXPLAIN 语句,但我可以很好地剪切和粘贴 SQL,而且我可以很好地阅读秒表。

我在这里说。

嵌入式视图,即使是简单的视图,也会给执行速度带来一些严重的痛苦。

我刚刚回答了我自己的问题,方法是使用类似于(或曾经是)类似于(使用我在 OP 中提出的 A、B、C 类比)的视图 G,从使用 E 的视图 F 中选择...一直到 A。

为单个过滤行选择结果花费的时间太长 - 大约 500 毫秒。

我通过减少沿途捕获的额外表格将其缩短到 200 毫秒。我在那里获得了一些东西,这并不令人震惊。看到多少有点震惊。

但后来我将视图 G 对视图 B 的使用替换为视图 G 的一部分,从而将 200 毫秒缩短到 7 毫秒。这使视图 G 的阅读变得更加复杂,但效率却惊人地高。

抽象出常见的连接就到此为止了。

所以这回答了我的第一个问题,一个响亮的 NO!在 PostgreSQL 中,使用嵌套视图的视图可能比完全不使用嵌套的逻辑等效视图效率低得惊人。

我的收获:如果性能受到影响,请不要认为您的嵌套视图是无辜的。他们很可能会伤害你。

很糟糕。

PS 我开始了解如何阅读 EXPLAIN 结果。更重要的是嵌套视图是用这个解释的......

->  Hash Join  (cost=20902.62..28364.33 rows=1 width=1018)
      (actual time=878.007..1092.339 rows=0 loops=3)
        Hash Cond: (mi.mft_item_id = ri.mft_item_id)

而我避免使用嵌套视图的观点导致了这一点......

->  Index Scan using mft_items_pkey on mft_items mi
      (cost=0.42..8.44 rows=1 width=187)
      (actual time=0.024..0.024 rows=1 loops=1)
        Index Cond: (mft_item_id = ri.mft_item_id)

当我将两个视图连接在一起时,PostreSQL 没有使用理想的索引。

【讨论】:

以上是关于简单的嵌套视图是不是有效(如果不包含多余的表?)的主要内容,如果未能解决你的问题,请参考以下文章

iOS 嵌套滚动视图——一直滚动到超级视图?

Flutter:嵌套 ListView 有效。嵌套的 SliverList 没有,但 ListView 包含 Sliver

将嵌套的 json 导入为具有多个嵌套的表

从价格中去除多余零的有效方法?

在 Angular 和 mongoose 中创建包含嵌套数据的表

Mvc 列出嵌套在 Viewmodel 中的多个视图