子查询 X 临时表 X 动态 sql X 表值函数
Posted
技术标签:
【中文标题】子查询 X 临时表 X 动态 sql X 表值函数【英文标题】:subquery X temp table X dynamic sql X table valued function 【发布时间】:2012-07-25 14:11:38 【问题描述】:我有一个为我的项目总结大量信息的视图。我们称之为 v_item_details。
此视图是通过递归 cte 定义的,如果未应用正确的过滤,可能会变得非常慢。基本上,如果我提供项目 ID 列表,事情就会顺利进行。所以像 SELECT * FROM v_item_details WHERE item_id IN(1,2,3)
这样的东西在 1 秒内运行。
当我尝试获取在另一个表中定义的一组项目的项目详细信息时,事情变得复杂了。查询 SELECT * FROM v_item_details WHERE item_id IN (SELECT item_id FROM items WHERE group_id = 1)
将花费 1 分钟以上,即使 group_id 已编入索引并且子查询返回与先前查询(1,2 和 3)相同的 item_id。
我尝试创建一个表变量并将子查询的结果插入其中,然后对其进行连接,但仍然花费了 1 多分钟。
接下来,我尝试使用接收 item_id 作为参数的表值函数包装我的视图,然后执行交叉应用,以尝试强制执行与简单选择相同的计划,但这需要 4 分钟!
现在我正在使用一个动态查询来选择 ID,然后执行快速子查询。但这不是最理想的,因为现在我被存储过程困住了,而不是我可以进一步操作的视图。
关于如何强制 SQL 首先选择子查询中的值然后运行快速子查询的任何想法?我认为使用 LOOP 连接查询提示会起作用,但它没有,因为虽然它确实从子查询开始执行循环,但视图的查询计划与快速查询不同,所以我仍然有性能问题。
最好的问候, 卡洛斯·乔丹
【问题讨论】:
【参考方案1】:如果有一个我们可以在我们自己的 SQL Server 实例上构建的实例来重现和诊断问题,将会很有帮助。如果没有,我可能会尝试以下几件事:
确保items
表上的统计信息是最新的
尝试使用 JOIN 而不是 IN 子句(我知道这些通常应该是相同的,但在某些情况下它们的行为非常不同,例如使用 COLUMNSTORE 索引,因此递归 CTE 也可能存在怪癖)
确保vw_item_details
中使用的表具有正确的主键和/或索引
尝试只选择您需要的列,而不是从 vw_item_details
中选择 *(这是一个远景,但您永远不知道...)
【讨论】:
以上是关于子查询 X 临时表 X 动态 sql X 表值函数的主要内容,如果未能解决你的问题,请参考以下文章
sql 表表达式 - 视图,临时表,表变量,派生表,表值函数,公用表表达式(CTE)
错误 SQL Server 2012:未为函数 X 提供参数