为什么使用Table Spool比不慢?

时间:2017-08-07 15:27:57

标签: sql-server query-performance

在sql server中运行两个类似的sqls,其中表TBSFA_DAT_CUST具有毫秒行且没有约束(没有索引和主键), 另外两个只有几行和普通主键:

对于较慢的一个:

SELECT A.CUST_ID, C.CUST_NAME, A.xxx  --and several specific columns
FROM TBSFA_DAT_ORD_LIST A JOIN VWSFA_ORG_EMPLOYEE B ON A.EMP_ID = B.EMP_ID
     LEFT JOIN TBSFA_DAT_CUST C ON A.CUST_ID = B.CUST_ID
     JOIN VWSFA_ORG_EMPLOYEE D ON A.REVIEW_ID = D.EMP_ID
WHERE ISNULL(A.BATCH_ID, '') != '' 

execution plan of slower one

f表示速度更快:

SELECT *
FROM TBSFA_DAT_ORD_LIST A JOIN VWSFA_ORG_EMPLOYEE B ON A.EMP_ID = B.EMP_ID
     LEFT JOIN TBSFA_DAT_CUST C ON A.CUST_ID = B.CUST_ID
     JOIN VWSFA_ORG_EMPLOYEE D ON A.REVIEW_ID = D.EMP_ID
WHERE ISNULL(A.BATCH_ID, '') != '' 

execution plan of faster one

f(大于0.6s)比s(大于4.6s)快得多。

否则,我找到了两种方法来快速进行f:

1.在表TBSFA_DAT_CUST.CUST_ID中添加constaint和primary key;

2.特定超过61列表TBSFA_DAT_CUST(共80列)。

我的问题是为什么sql优化器在SELECT子句中的特定列而不是'*'时使用Table Spool,为什么使用Table Spool执行得更慢?

我的问题是关于

1 个答案:

答案 0 :(得分:0)

在较慢的查询中,您将结果集限制为特定列。由于这是一个未索引的非约束表,优化器正在从原始表扫描创建一个临时表,只需要所需的特定列。然后它通过临时表上的嵌套循环运算符运行。当它知道它需要表上的每一列(Select *)时,它可以直接在表扫描中运行嵌套循环操作符,因为扫描的结果集将完全连接到顶层表。

除此之外,您的查询还有其他一些问题:

LEFT JOIN TBSFA_DAT_CUST C ON A.CUST_ID = B.CUST_ID

你在这里没有加入任何东西,你将整个表加入到每一条记录中。是a.cust_id = c.cust_id还是b.cust_id = c.cust_id还是a.cust_id = c.cust_id and b.cust_id = c.cust_id

此外,where子句中的此函数毫无意义,可能会降低性能:

WHERE ISNULL(A.BATCH_ID, '') != '' 

将其更改为:

WHERE A.BATCH_ID is not null and A.Batch_ID <> ''