Optimierung von Datenbankmodellen–SARGable Abfragen
Ich bekam heute eine recht interessante Aufgabe auf den Tisch. Ein Kunde beklagte sich über die schlechte Ausführungsgeschwindigkeit einer Abfrage, der er von einem Programmierer erhalten hatte. Mir wurde der Code für die View zugeschickt und das Problem war sehr schnell gefunden. Statt eines Indexseek hat die Abfrage nur einen Indexscan durchgeführt. Ursache war, das die WHERE-Klausel keine SARGable Argumente verwendete. Mit diesem Artikel möchte ich aufzeigen, was SARGable ist und wie es funktioniert.
Problemstellung
Um das Problem zu reproduzieren, wird erneut die Datenstruktur aus den bereits zuvor geschriebenen Artikeln zur Optimierung von Datenmodellen verwendet. Die Relation dbo.tbl_Companies besitzt die folgende Struktur:
CREATE TABLE dbo.tbl_Companies
(
Id int IDENTITY(1,1) NOT NULL,
Name nvarchar(128) NULL,
TaxNo varchar(24) NULL,
CostCenter char(7) NULL,
UpdateBy varchar(20) NULL
);
GO
CREATE UNIQUE CLUSTERED INDEX ci_tbl_Companies_Id ON dbo.tbl_Companies (Id);
CREATE INDEX ix_tbl_Companies_CostCenter ON dbo.tbl_Companies (CostCenter) INCLUDE (Name, TaxNo);
Der Code der gelieferten View sah - auf die obige Datenstruktur angepasst - wie folgt aus:
SELECT Id, Name, TaxNo, CostCenter FROM dbo.tbl_Companies WHERE LEFT(CostCenter, 1) = 'A'
Da auf der Relation ein Index ix_tbl_Companies_CostCenter liegt, ist zu erwarten, dass dieser Index verwendet wird und ein Indexseek angewendet wird. Der Ausführungsplan zeigt jedoch ein ganz anderes Ergebnis an.
Man kann erkennen, dass zwar der Index ix_tbl_Companies_CostCenter verwendet wird; jedoch wird statt eines optimalen Indexseek ein Indexscan ausgeführt. Woran liegt das?
Problemanalyse
Die Ursache für dieses Verhalten des Microsoft SQL Servers ist verständlich, da Microsoft SQL Server für JEDE Zeile der Relation dbo.tbl_Companies die Funktion SUBSTRING ausführen muss (siehe Details des Ausführungsplans). Somit handelt es sich um ein "Predicate" aber KEIN "Seek Predicate".
Das gleiche Ergebnis erreicht man auch mit der folgenden Abfrage:
SELECT Id, Name, TaxNo, CostCenter FROM dbo.tbl_Companies WHERE CostCenter LIKE 'C%';
Sehr deutlich wird erkennbar, dass Microsoft SQL Server mit dem Operator LIKE ein "Seek Predicate" bilden kann. In diesem Fall können mengenorientierte Abfragen auf die Relation durchgeführt werden, die durch einen Indexseek beeinflusst werden.
Weitere Beispiele für SARGable Abfragen:
non SARGable | SARGable |
SELECT * FROM dbo.tbl_Companies WHERE Id + 1 = 10 | SELECT * FROM dbo.tbl_Companies WHERE Id = 10 |
SELECT SId, SortName, InsertDate FROM dbo.tbl_Stammdaten WHERE YEAR(InsertDate) = 2012 |
SELECT SId, SortName, InsertDate |
Fazit
Es ist unumgänglich, bei der Suche nach Optimierungsmöglichkeiten auch die Details eines Abfrageplans zu beachten. Es sollte immer das Ziel bei Einschränkungen mittels WHERE-Klausel sein, eine SEEK-Einschränkung (Predicate) zu erzielen. Funktionen und Operationen von Attributen verhindern in der Regel diesen Optimierungsschritt.
Herzlichen Dank für's Lesen
Print article | This entry was posted by Uwe Ricken on 26.11.12 at 18:54:00 . Follow any responses to this post through RSS 2.0. |