栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

指望有条件的大表联接很慢

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

指望有条件的大表联接很慢

您的查询,已重写且100%等价:

SELECt count(*)FROM   product_categories   pc JOIN   customers c  USING (organization_id) JOIN   total_sales          ts ON ts.customer_id = c.idJOIN   performance_analyses pa ON pa.total_sales_id = ts.idWHERe  pc.organization_id = 3AND    c.active  -- boolean can be used directlyAND    c.visibleAND    ts.product_category_id = pc.idAND    ts.period_id = 193AND    pa.size > 0;

另一个答案建议将所有条件移到

FROM
列表中的连接子句和顺序表中。这可能适用于具有相对原始查询计划程序的某些其他RDBMS。但是,尽管它对Postgres也没有害处,但它对查询的
性能没有影响
-假设使用默认服务器配置。手册:

明确的内连接语法(

INNER JOIN
CROSS JOIN
,或古拙
JOIN
)在语义上的相同列出输入关系
FROM
,所以
不约束连接顺序

大胆强调我的。还有更多内容,请阅读手册。

关键设置为

join_collapse_limit
(默认为 8
)。无论您如何安排表格以及是否将条件写为
WHERe
JOIN
子句,Postgres查询计划器都会以它希望最快的方式重新安排您的4个表格。没什么区别。(对于某些其他类型的无法自由重排的联接,情况并非如此。)

重要的是,这些不同的连接可能性在语义上等效,但是执行成本可能大不相同。因此,计划者将探索所有这些因素,以找到最有效的查询计划。

最后,

WHERe id IN (<subquery>)
通常
等同于联接。对于右侧的重复匹配值,它不会在左侧乘以行。子查询的列在其余查询中不可见。联接可以将具有重复值的行相乘,并且可见列。
在这两种情况下,您的简单子查询都将挖掘一个唯一的列,因此在这种情况下没有有效的区别-除了
IN(<subquery>)
通常(至少有点)更慢且更冗长。使用联接。

您的查询

指标

product_categories
有34行。除非您计划添加更多表,否则索引不会对该表产生帮助。顺序扫描将始终更快。放下
index_product_categories_on_organization_id

customers
有6,970行。索引开始变得有意义。但是您的查询根据
EXPLAIN
输出使用了4,988个。只有对
索引 宽不到表的
索引进行仅索引扫描才有
帮助。假设
WHERe active AND visible
是常量谓词,我建议使用部分多列索引:

CREATE INDEX index_customers_on_organization_id ON customers (organization_id, id)WHERe active AND visible;

我附加

id
了允许仅索引扫描。否则,该列在此查询的索引中无用。

total_sales
有7,104,441行。索引非常重要。我建议:

CREATE INDEX index_total_sales_on_product_category_customer_idON total_sales (period_id, product_category_id, customer_id, id)

再次,针对仅索引扫描。这是最重要的。

您可以删除完全冗余的索引

index_total_sales_on_product_category_id

performance_analyses
有1,012,346行。索引非常重要。我会建议另一个带有条件的部分索引
size > 0

CREATE INDEX index_performance_analyses_on_status_idON performance_analyses (total_sales_id)WHERe pa.size > 0;

然而:

筛选器删除的行:0“

似乎这种情况毫无用处?是否有任何

size > 0
不正确的行?

创建这些索引后,您 需要 访问

ANALYZE
表。

表格统计

通常,我看到许多错误的估计。Postgres 低估 了几乎每一步返回的行数。我们看到的 嵌套循环
对于更少的行会更好。除非这是不太可能的巧合,否则表统计信息将严重过时。您需要访问自动真空设置,还可能需要访问两个大表

performance_analyses
和的每表设置
total_sales

你已经没有运行

VACUUM
ANALYZE
,这让查询更慢。那没有多大意义。我将
VACUUMFULL
在这两个表上运行一次(如果您能负担得起独占锁)。否则尝试
pg_repack

考虑到所有的统计数据和糟糕的计划,我会考虑
vacuumdb -fzyourdb
在您的数据库上运行一个完整的数据库。那会在原始条件下重写所有表和索引,但是定期使用是不好的。这也很昂贵,并且将锁定您的数据库更长的时间!



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/431742.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号