立即执行的 SELECT 语句,需要永远插入表变量

Posted

技术标签:

【中文标题】立即执行的 SELECT 语句,需要永远插入表变量【英文标题】:SELECT statement that executes instantly, takes forever to insert into table variable 【发布时间】:2012-11-08 01:37:36 【问题描述】:

我在下面有以下 SQL 代码。完成需要很长时间,但如果我只运行 SELECT DISTINCT ID, ParentID FROM Y WHERE ID IN (3,4),它会立即完成。

DECLARE @table TABLE
(
  ID int,
  ParentID int
)

INSERT INTO @table 
SELECT DISTINCT ID, ParentID FROM Y WHERE ID IN (3,4)

SELECT * FROM @table

这是怎么回事,这毫无意义。

【问题讨论】:

发布两个版本的查询计划。 我们在这里谈论多少 插入表变量的查询的一个限制是它们不能使用并行计划。 【参考方案1】:

尝试改用临时表。表变量仅针对一行进行了优化,并假设它将得到什么。

阅读更多here

【讨论】:

使用临时表的解决方案可能有效。这是因为“表变量仅针对一行进行了优化”的解释是无稽之谈。两者之间插入性能的任何差异都是因为并行计划与串行计划。【参考方案2】:

尽管它是一个几乎可以立即执行的简单 SELECT,但如果您有一个大型数据集,IN 将花费更长的时间,因为它会在处理条件之前收集所有数据。在它的位置使用并存在,它很可能会运行得更快。

【讨论】:

整个事情(包括最后的 SELECT *)需要那么长时间吗?您需要将其取出并将其隔离以验证它是 INSERT 而不是最终的 SELECT 花费了这么长时间。【参考方案3】:

这种行为可能有多种原因。没有执行计划,我们只能猜测原因,不能确定确切的原因。

    由于您在查询中使用DISTINCT ID,我假设ID 不是主键。您能否修改您的查询以在WHERE 子句中使用PK

    可能是Y表数据太大,几百万的量级,由于缺少if indexing(on the table) & Exists(in the query),查询会占用很久了。

    试试这个代码只是为了检查速度

    SELECT DISTINCT ID, ParentID
    FROM Y WHERE ID IN (3,4)
    

【讨论】:

以上是关于立即执行的 SELECT 语句,需要永远插入表变量的主要内容,如果未能解决你的问题,请参考以下文章

如何将表名分配给变量并在立即执行语句中使用相同的

MySQL存储过程循环遍历变量并插入临时表

如何在执行立即语句中包含变量?

插入(或更新)到基表后视图是不是立即更新

Oracle中触发器内的select语句出现错误的绑定变量错误

使用传递给过程的动态表名立即执行