Sql-Server

無法消除索引掃描

  • September 25, 2015

我有一個查詢,即使使用 SQL Sentry,我也無法消除索引掃描。

這是查詢:

SELECT TOP 30 codCliente FROM (
       SELECT t1.CodCliente, codcampo, valor, t1.chavealeat 
       FROM tblCliente AS t1 WITH(NOLOCK) 
           INNER JOIN tblClienteDetalhe AS t2 WITH(NOLOCK) 
           ON t1.codcliente = t2.codcliente 
           AND CodCampo IN(-1, 4)
       WHERE codStatus IN (0)  
           AND t1.ChavePeriodo < GETDATE()
           AND t1.CodStatusLigacao = 0
           AND EXISTS
           (
               SELECT codcliente FROM tblclientedetalhe WITH(NOLOCK) 
               WHERE codcampo = 3 AND valor = '2' 
                   AND codcliente = t1.codcliente
           )
           AND EXISTS
           (
               SELECT codcliente FROM tblclientedetalhe WITH(NOLOCK) 
               WHERE codcampo = 6
                   AND CONVERT(DATETIME, Valor) BETWEEN '2015-08-01' AND '2015-08-31'
                   AND DATEDIFF(DAY, Valor, GETDATE()) > 15
                   AND codcliente = t1.codcliente
           )
           AND NOT EXISTS
           (
               SELECT 0 FROM tblPesquisa WITH(NOLOCK)
               WHERE tblPesquisa.CodCliente = t1.CodCliente
           )
           AND EXISTS
           (
               SELECT codcliente FROM tblclientedetalhe WITH(NOLOCK) 
               WHERE codcampo = 4 and valor = '202' and codcliente = t1.codcliente
           )
   ) AS Cliente 
Pivot (MAX(Valor) FOR codCampo in ([4])) AS PivotTable
WHERE (((([4] = '202')))) 
ORDER BY chavealeat;

這是我做的索引:

create index IX_CHAVEALEAT_CODCLIENTE
on tblcliente (chavealeat,codcliente)
include (chaveperiodo,codstatus,codstatusligacao)

而且,這是分析:

覆蓋指數

為什麼顯示計劃index scan?我涵蓋了所有專欄。我曾經option(recompile)更新計劃。

這個索引有錯嗎?輸出只有codcliente.

分析

當時我有 10-30 個查詢正在執行,並且沒有 wait_info 問題。

僅僅因為你有一個覆蓋索引並不意味著它不會掃描,也不意味著掃描仍然不是訪問請求數據的最佳方式。

你要返回,什麼,300 萬行?即使這不是表的大部分內容,執行 300 萬次查找操作仍然沒有多大意義,查找第一行並對其餘行執行範圍掃描也不可能有任何好處。還有一個問題是多個EXISTS子句——其中多個不連接到索引的前導鍵列——不可能都能夠利用查找的相同輸出。而且您在所有列上都有過濾器INCLUDE-它們不是鍵的一部分,因此在這些列上查找將很困難(實際上,我看到索引仍然用於查找的唯一情況是WHERE針對非鍵列的子句是該列是BIT,並且這些場景並沒有引入您上面的所有其他變數)。你也在使用PIVOT和聚合,我敢肯定這沒有幫助。

另外,在什麼表CodCampo中(為什麼它沒有正確地以表別名作為前綴)?您可能會遇到以下兩個問題中的一個或兩個:

  1. 這是一個OR可以阻止尋求的析取(子句)(請參閱此處保羅的回答)。
  2. 如果它在 中tblcliente,那麼您的索引無論如何都不會覆蓋。

您可以嘗試使用FORCESEEK提示執行查詢(在 Paul 的範例中也提到過),它要麼無法生成計劃(不太可能),要麼您將獲得可以與我們共享的計劃,如果您還共享掃描計劃,您如果沒有提示,我們可以進一步了解 SQL Server 選擇掃描的原因。

順便說一句(這肯定不會幫助你找到答案),因為估計值要低得多,我會檢查你的統計數據是否是最新的。

最後,不要總是認為掃描不好並且需要消除一些東西!在很多情況下,掃描確實是檢索數據的最佳方式。

引用自:https://dba.stackexchange.com/questions/116189