【发布时间】:2022-11-01 20:33:06
【问题描述】:
所有这一切的目的是创建一个查找表以避免自连接,这将涉及将相同数据与更大的数据集连接。
在这种情况下,销售订单可能具有开单给客户 ID 和发运给客户 ID 中的一个或两个。
这里的表格是来自 5 个不同服务器的数据聚合,由 box_id 区分。客户表约为 170 万行,sales_order 约为 5500 万行。最终结果是大约 5200 万条记录,平均需要大约 80 分钟才能运行。
查询:
SELECT DISTINCT sog.box_id ,
sog.sales_order_id ,
cb.cust_id AS bill_to_customer_id ,
cb.customer_name AS bill_to_customer_name ,
cs.cust_id AS ship_to_customer_id ,
cs.customer_name AS ship_to_customer_name
FROM sales_order sog
LEFT JOIN customer cb ON cb.cust_id = sog.bill_to_id AND cb.box_id = sog.box_id
LEFT JOIN customer cs ON cs.cust_id = sog.ship_to_id AND cs.box_id = sog.box_id
执行计划:
https://www.brentozar.com/pastetheplan/?id=SkjhXspEs
所有这些都发生在 SQL Server 上。
我尝试将账单复制到 CTE 并将其运送到客户集并加入这些集,但没有发现任何性能优势。
这些表上的唯一索引是主键(合成 ID)。有点奇怪的是,执行计划分析器不建议向任一表添加任何索引。它通常希望我对几乎所有内容都进行索引。
我不知道一定有办法让它运行得更快,但我正在努力改进我的查询优化并且已经达到了我的知识极限。非常感谢任何见解。
【问题讨论】:
-
您的查询正在对两个表执行表扫描并扫描
Customer两次。(Cust_Id) include (Customer_Name)上的覆盖索引可能是有益的,但理想情况下,您应该只点击一次表格,您可以使用outer apply()中的条件逻辑来完成。最好有实际的计划而不是估计的计划以确定最大的成本在哪里。你需要清楚的? -
@@version是什么?理想情况下,此查询可以受益于批处理模式 -
“平均需要大约 80 分钟才能运行” - 在哪里?如果您将大约 52M 记录返回给客户端,那么您可能会看到大量等待,因为这跟不上。 80 分钟只对中等大小的表和一些哈希连接进行三表扫描,否则肯定会出乎意料地慢......
-
实际执行计划的 XML 是什么。没有估计。看起来像? (这将包含遇到的等待统计信息和每个操作员的时间以及任何溢出的详细信息)
标签: sql sql-server query-optimization materialized-views