Sql-Server
如何擺脫這些關鍵查找?
我有這個查詢:
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
在您的SELECT
、WHERE
和ORDER BY
.使用舊索引的原因是它更適合查詢。這部分是因為索引
Vit_DataAberturaReal
阻止了計劃中的排序運算符 - 因為數據已經正確排序。這也是因為新索引中的第一列在您的查詢中是無用的non-sargable。如果您可以刪除RTRIM
、LTRIM
和LOWER
,那麼性能可能會更好。如果索引只是為了支持這個查詢,你可以考慮添加
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