Sql-Server

如何擺脫這些關鍵查找?

  • May 24, 2017

我有這個查詢:

   SELECT TOP (20) table1.Vit_Codigo
   ,table1.Vit_Nome
   ,table1.Vit_Apelido
   ,table1.Vit_codigoStatus
   ,table1.Vit_Numero
   ,table1.Vit_Ano
   ,table1.Vit_CodigoTiposExames
   ,table3.Esp_Setor
   ,table2.TEs_Descricao
FROM table1
LEFT JOIN table2 ON tb_Vitima.Vit_CodigoTiposExames = table2.TEs_Codigo
LEFT JOIN table3 ON table3 .Esp_Codigo = table1.Vit_CodigoEspecialidade
WHERE (rtrim(ltrim(lower(tb_Vitima.Vit_Rg))) = 'n/a')
   AND (
       table1.Vit_codigoStatus IN (
           3
           ,4
           )
       )
ORDER BY table1.Vit_DataAberturaReal DESC

這些計劃:

在此處輸入圖像描述

在此處輸入圖像描述

我做了這個索引:

create index IX_SELECTTOP20_INCLUDE 
   on table1
   ( Vit_Rg ,Vit_codigoStatus )
include (
Vit_Codigo , Vit_Nome , Vit_Apelido , Vit_Numero ,
              Vit_Ano , Vit_CodigoTiposExames )

…但似乎程式碼正在使用舊索引。

那麼,為什麼我的索引仍然使用鍵查找?

兩個指數似乎都沒有“覆蓋”。為避免鍵查找,您必須至少INCLUDE在您的SELECTWHEREORDER BY.

使用舊索引的原因是它更適合查詢。這部分是因為索引Vit_DataAberturaReal阻止了計劃中的排序運算符 - 因為數據已經正確排序。這也是因為新索引中的第一列在您的查詢中是無用的non-sargable。如果您可以刪除RTRIMLTRIMLOWER,那麼性能可能會更好。

如果索引只是為了支持這個查詢,你可以考慮添加WHERE Vit_codigoStatus IN (3,4)到你的索引定義中。

理想情況下,這些WHERE列將是索引本身的一部分 - 而不是在INCLUDE. 如果我要專門創建一個索引來支持這個查詢,它可能是這樣的:

CREATE INDEX [IX_SELECTTOP20_INCLUDE]
   ([Vit_DataAberturaReal])
INCLUDE(
   [Vit_Codigo], [Vit_Nome], [Vit_Apelido], [Vit_codigoStatus],
   [Vit_Numero], [Vit_Ano], [Vit_CodigoTiposExames],
   [Vit_CodigoEspecialidade], [Vit_Rg]) 
WHERE [Vit_Rg] = 'n\a' AND [Vit_codigoStatus] IN ( 3, 4 )

注意:這將不支持LTRIM(RTRIM(LOWER(...))).

因為您的新索引沒有排序

嘗試沒有 Vit_DataAberturaReal 上的排序

排序上的索引不包括選擇中的所有欄位

create index IX_SELECTTOP20_INCLUDE 
   on tb_vitima 
       ( Vit_Rg ,Vit_codigoStatus )
include ( Vit_Codigo,  Vit_Nome 
       , Vit_Apelido
       , Vit_Numero, Vit_Ano 
       , Vit_CodigoTiposExames )

SELECT TOP(20) tb_Vitima.Vit_Codigo,  tb_Vitima.Vit_Nome   
            , tb_Vitima.Vit_Apelido, tb_Vitima.Vit_codigoStatus 
            , tb_Vitima.Vit_Numero,  tb_Vitima.Vit_Ano 
            , tb_Vitima.Vit_CodigoTiposExames
            , lst_Especialidades.Esp_Setor, lst_TiposExames.TEs_Descricao 
FROM tb_Vitima 
LEFT OUTER JOIN lst_TiposExames 
    ON tb_Vitima.Vit_CodigoTiposExames = lst_TiposExames.TEs_Codigo 
   AND tb_Vitima.Vit_codigoStatus in(3, 4) 
LEFT OUTER JOIN lst_Especialidades 
    ON lst_Especialidades.Esp_Codigo = tb_Vitima.Vit_CodigoEspecialidade 
   AND rtrim(ltrim(lower(tb_Vitima.Vit_Rg))) = 'n/a'

order by tb_Vitima.Vit_DataAberturaReal desc

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