Ota yhteyttä

Kääritään hihat ja tehdään tuloksia!

Lähetä meille viesti

SARGable kyselyt (Search Argument-able queries) ovat kyselyitä, joissa indeksejä voidaan käyttää hyödyksi kun filtteröidään dataa, joko joinilla tai where -lauseella. Pelkkä indeksin lisääminen ei siis välttämättä paranna suorityskykyä, vaan kysely tulee tehdä tavalla, jolla Sql Server osaa hyödyntää indeksejä.

Demo datana toimii vastaava varasto, joka sisältää automallin, satunnaisen vuosiluvun ja luontipäivän:

DROP TABLE IF EXISTS dbo.CarInventory
CREATE TABLE dbo.CarInventory
(
    ID int IDENTITY(1,1),
    Name VARCHAR(100),
    Year int,
    CreateDate DATETIME2 DEFAULT GETDATE()
)
GO

CREATE NONCLUSTERED INDEX IX_CreateDate ON dbo.CarInventory (CreateDate) INCLUDE (Name)
CREATE NONCLUSTERED INDEX IX_Name ON dbo.CarInventory (Name)

Otetaan ensimmäisenä kysely, joka ei pysty hyödyntämään indeksiä halutulla tavalla:

SELECT Name
FROM dbo.CarInventory
WHERE Convert(varchar(8), CreateDate, 112) > '20170101'

Non-sargable execution plan

Execution planista nähdään, että Numbers of Rows Read on 330, joka vastaa koko taulua. Actual Number of Rows on kuitenkin vain 164. Tämä johtuu siitä, että Sql Server joutuu konvertoimaan jokaisen rivin CreateDate sarakkeen, jotta se pystyy filtteröimään datan.

Tähän helppo parannus:

SELECT Name
FROM dbo.CarInventory
WHERE CreateDate > CAST('20170101' as datetime2)

Sargable execution plan

Nyt Sql Serverin ei tarvitse käydä jokaista riviä läpi, vaan konvertointi tehdään vain kerran. Tästä johtuen taulusta luetaan vain tarvittavat 164 riviä.

Sql Server on myös sen verran fiksu, että se osaa tehdä konvertoinnin automaattisesti.

SELECT Name
FROM dbo.CarInventory
WHERE CreateDate > '20170101'

Sargable execution plan - implicit convert

Tulos on sama, mutta Sql Server huolehti konvertoinnin.

Toinen versio:

SELECT Name
FROM dbo.CarInventory
WHERE MONTH(CreateDate) = 6
AND YEAR(CreateDate) = 2017

Myös funktiota kutsuttaessa konvertointi tehdään sarakkeelle, jolloin funktiota kutsutaan taulun jokaisella rivillä.

Tämäkin voidaan korjata:

SELECT Name
FROM dbo.CarInventory
WHERE CreateDate >= '20170601' and  CreateDate < '20170701'

Näillä voi olla todella suuri merkitys suorituskyvyn kannalta, joten kannattaa olla tarkkana kuinka kyselynsä rakentaa. Netistä löytyy hyvin esimerkkejä, kuinka omasta ympäristöstään voi bongata kyselyitä, joissa on mahdollisesti edellä mainittuja ongelmia.