lot*_*lot 6 sql sql-server join
我需要从BUNDLES表中选择具有多个SAP_STATE_ID值之一的行.这些值取决于是否应该导出相应的SAP状态.
此查询运行速度非常快(SAP_STATE_ID字段上有索引) -
SELECT b.* FROM BUNDLES b WHERE b.SAP_STATE_ID IN (2,3,5,6)
Run Code Online (Sandbox Code Playgroud)
但是......我想动态获取ID列表,如下所示:
SELECT b.* FROM BUNDLES b
WHERE b.SAP_STATE_ID IN
(SELECT s.SAP_STATE_ID FROM SAP_STATES s WHERE s.EXPORT_TO_SAP = 1)
Run Code Online (Sandbox Code Playgroud)
而且,这个查询突然花费了太多时间.我希望SQL服务器首先运行子查询(它不依赖于主查询中的任何内容),然后像我的第一个例子一样运行整个事情.我试图重写它以使用连接而不是子查询:
SELECT b.* FROM BUNDLES b
JOIN SAP_STATES s ON (s.SAP_STATE_ID = b.SAP_STATE_ID)
WHERE s.EXPORT_TO_SAP = 1
Run Code Online (Sandbox Code Playgroud)
但它的性能相同.它似乎正在为BUNDLES表的每一行运行子查询或类似的东西.我在阅读执行计划方面不是很熟练,但我试过了.它说81%的成本用于扫描BUNDLES的主键索引(我不知道为什么它应该这样做,有BUNDLE_ID字段定义为PRIMARY KEY,但它根本没有出现在查询中...... )
有没有人解释为什么SQL服务器如此"愚蠢"?有没有办法以良好的性能实现我想要的但不需要提供SAP_STATE_ID的静态列表?
表和相关索引的脚本 - http://mab.to/xbYiI0wKj
子查询版本的执行计划 - http://mab.to/8Qh6gpdYZ
带连接的版本的查询计划 - http://mab.to/YCqeGCUbr
(出于某种原因,这两个计划看起来是一样的,都建议创建BUNDLES.SAP_STATE_ID索引,已经存在)
我很确定你的统计数据是错误的。如果您想让它快速工作,我会将查询编写为:
SELECT b.*
FROM SAP_STATES s
INNER LOOP JOIN BUNDLES b
ON s.SAP_STATE_ID = b.SAP_STATE_ID
WHERE s.EXPORT_TO_SAP = 1
Run Code Online (Sandbox Code Playgroud)
这会强制使用嵌套循环连接来SAP_STATES过滤BUNDLES
| 归档时间: |
|
| 查看次数: |
1029 次 |
| 最近记录: |