子查询 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 中使用表值函数而不是临时表?

sql 表表达式 - 视图,临时表,表变量,派生表,表值函数,公用表表达式(CTE)

错误 SQL Server 2012:未为函数 X 提供参数

数据库原理与应用(SQL Server)笔记 第十章 用户定义函数

SQL Server:表值函数不适用于子查询

sql 表值函数-将一个传入的字符串用2中分隔符拆分成临时表