Šajā rakstā daži likumi, kas neļauj SQL vaicājumu optimizātoram "izdomāt", ka var izmantot indeksus. Lai ilustrētu ar piemēru, izmantošu dbo.TestTable tabulu ar indeksu uz kolonnas "skaitlis" (jau sastapta vairākos rakstos iepriekš):
Create Table dbo.TestTableLai varētu analizēt vaicājumu rezultātus, uzstādīsim, lai tiek parādīta IO Statistika:
(
TestTableID int Identity primary key,
Skaitlis int,
TrisBurti char(3),
MainigsGarums NVarChar(20),
GarsTeksts NVarChar(100)
)
Go
Set NoCount ON
Declare @i int
Set @i = 0
While @i < 10000
Begin
Insert Into dbo.TestTable(Skaitlis, TrisBurti, MainigsGarums, GarsTeksts)
Values(Cast(Rand()*1000 as int), 'abc', Replicate('x', Cast(Rand()*20 as int)), Replicate('x',100));
Set @i = @i + 1;
End
Go
Create Index IX_Skaitlis On dbo.TestTable
(
Skaitlis
)
set statistics io onEfektīvs vaicājums uz šo tabulu un attiecīgo indeksu izskatītos šādi:
select TestTableID from dbo.TestTableTiek veiktas 2 loģiskās lasīšanas operācijas, tas nozīmē, ka indeksā tika atrasta vajadzīgā vērtība un attiecīgās indeksa beigu virsotnes (kurā glabājas TestTableID. Ja nav skaidrs kāpēc tāds apgalvojums, tad šeit var palasīt: Indeksi (non-clustered indexes)).
where skaitlis = 11
Sliktie un labie piemēri
1. Neizmantot matemātiskas darbības uz indeksa kolonnas jo tādā gadījumā indeksā vērtība tiks meklēta to pārlasot, nevis meklējot konkrēto vērtību! Šādi tiek veiktas 20 loģiskās lasīšanas operācijas:
select TestTableID from dbo.TestTabletā vietā pavisam mierīgi matemātisko operāciju var pārnest uz otru pusi un atkal iegūt 2 loģiskās lasīšanas operācijas (lieki piebilst- rezultāti būs identiski):
where (skaitlis - 1) = 11
select TestTableID from dbo.TestTable2. Neizmantot tipa konversāciju uz indeksa kolonnas kad vien iespējams. Notiek tas pats kas iepriekš, 20 loģiskās lasīšanas operācijas (starp citu, šis varētu būt tipisks gadījums uz datuma kolonnas, kad meklē konkrēta datuma rindas lai atbrīvotos no laika daļas- cast uz datuma pataisot par nvarchar un salīdzina ar tekstu. Tādā gadījumā varētu apsvērt Between izmantošanu, lai izvairītos no cast):
where skaitlis = 11 + 1
select TestTableID from dbo.TestTableŠādi būs 2 loģiskās lasīšanas operācijas:
where cast(skaitlis as nvarchar) = '12'
select TestTableID from dbo.TestTable3. Neizmantot funkcijas uz indeksa kolonnas. Atkal 20 loģiskās lasīšans operācijas:
where skaitlis = cast('12' as int)
select TestTableID from dbo.TestTableTā vietā var panākt to pašu rezultātu, bet jau tikai 2 loģiskās lasīšanas operācijas:
where Power(skaitlis,2) = 144
select TestTableID from dbo.TestTableKopsavilkums
where skaitlis = SQRT(144)
Tātad tāds pamata likums varētu būt- kad vien iespējams, visas darbības veikt ar mainīgo, nevis ar indeksa kolonnu.
Lai arī aprakstītie likumi ir samērā vienkārši, bieži vien par tiem aizmirst vai nemaz neiedomājas.
Ak jā, un lai pēc sevis satīrītu:
drop table dbo.TestTable
Nav komentāru:
Ierakstīt komentāru