【发布时间】:2014-09-30 15:25:00
【问题描述】:
我需要从 BUNDLES 表中选择具有几个 SAP_STATE_ID 值之一的行。这些值取决于是否应该导出相应的 SAP 状态。
这个查询运行得非常快(在 SAP_STATE_ID 字段上有索引) -
SELECT b.* FROM BUNDLES b WHERE b.SAP_STATE_ID IN (2,3,5,6)
但是...我想动态获取 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)
哎呀,这个查询突然花费了太多时间。我希望 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
但它的性能同样很差。似乎它正在为 BUNDLES 表的每一行或类似的东西运行子查询。我在阅读执行计划方面不是很熟练,但我试过了。它说 81% 的成本是用于扫描 BUNDLES 的主键索引(我不知道为什么要这样做,有 BUNDLE_ID 字段定义为 PRIMARY KEY,但它根本没有出现在查询中...... )
有没有人解释一下为什么 SQL Server 如此“愚蠢”?有没有办法以良好的性能实现我想要的,但无需提供 SAP_STATE_ID 的静态列表?
表和相关索引的脚本 - http://mab.to/xbYiI0wKj
子查询版本的执行计划 - http://mab.to/8Qh6gpdYZ
带有连接的版本的查询计划 - http://mab.to/YCqeGCUbr
(由于某种原因,这两个计划看起来相同,并且都建议创建 BUNDLES.SAP_STATE_ID 索引,该索引已经存在)
【问题讨论】:
-
你有关于 SAP_STATES.SAP_STATE_ID 的索引吗?
-
对,其实是主键
-
子查询自己运行需要多长时间?
-
发布带有索引定义的架构可能会有所帮助。
-
能否将查询计划保存为 .sqlplan 文件并与我们共享?
标签: sql sql-server join