Sql server 为什么使用工作台假脱机比不使用慢?

Sql server 为什么使用工作台假脱机比不使用慢?,sql-server,table-spool,query-performance,Sql Server,Table Spool,Query Performance,sql server中运行着两个类似的sql,其中TBSFA_DAT_CUST表有millons行,并且没有约束(没有索引和主键), 另外两个只有几行和普通主键: 慢一点的: 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 TBS

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

慢一点的:

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, '') != '' 

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, '') != '' 

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

否则,我找到了两种方法使s变快为f:

1.在表TBSFA_DAT_CUST.CUST_ID中添加Constant和主键

2.表TBSFA_DAT_CUST的具体内容超过61列(共80列)

我的问题是,当我在SELECT子句中指定列而不是“*”时,为什么sql优化器使用表假脱机,为什么使用表假脱机执行速度较慢


我的问题是关于

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

除此之外,您的查询还有几个其他可能的问题:

LEFT JOIN TBSFA_DAT_CUST C ON A.CUST_ID = B.CUST_ID
这里您没有加入任何内容,而是将整个表加入到每个记录中。是指
a.cust\u id=c.cust\u id
还是
b.cust\u id=c.cust\u id
还是
a.cust\u id=c.cust\u id和b.cust\u id=c.cust\u id

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

WHERE ISNULL(A.BATCH_ID, '') != '' 
将其更改为:

WHERE A.BATCH_ID is not null and A.Batch_ID <> ''
其中A.BATCH\u ID不为空且A.BATCH\u ID“”

确保至少运行两次,这样就可以省去创建计划的时间。除此之外,我的猜测是,
select*
,SQL知道它必须进行表扫描,所以它甚至不尝试进行某些“优化”。然而,通过选择单独的列,它尝试了,在这种情况下,没有做得更好。表假脱机意味着SQL基本上会抛出临时表中的所有数据,以便稍后在查询中重用。虽然这本身并不坏,但它需要一些时间,这可能只是一个优化器丢球的情况!为了得到平均成本,我已经运行了几十次这些sql。执行计划显示,两个sql都进行了表扫描。我想知道的是,为什么sql optimizer在我指定列时选择使用表假脱机,以及在这期间发生了什么使它变慢?正如我所知,通常,选择特定的列应该比不选择要快。很可能是因为它是一个很宽的表。当您选择*时,它意识到这是一大堆数据,并认为表假脱机会浪费时间和精力。当您限制列时,它认为它现在处于阈值之下,假脱机数据可能是一个好的调用。如果表上没有索引,SQL就无法了解数据的统计信息,因此估计结果会更糟。这也可能是(除其他原因外)向表中添加索引提高性能的原因。是的,这很有意义。感谢您的解释!