SQL Server på svenska
En svensk blogg om SQL Server, skriven på svenska. Kodexempel, fördjupningar och reflexioner på vad som händer i SQL Server-världen
Att jämföra exakt och ungefärligt


.NET (1) BLOB (1) Bloggen (2) DBA (2) Design (1) Felhantering (1) Installation (1) Optimering (4) Säkerhet (1) SQL Server 2000 (2) SQL Server 2005 (2) SQL Server 2008 (1)


 Wednesday, April 23, 2008
« Vaddå klusterindex? | Main | Varför jag inte skulle använda... »
Att jämföra exakt och ungefärligt

Via en bloggpost från Adam Machanic har jag deltagit i en tävling om ett exemplar av Expert SQL Server 2005 Development. Frågan från Adam är:

Givet att du har två tabeller, som skapats med scriptet nedan:

USE TempDB
GO

CREATE TABLE b1 (blat1 CHAR(5) NOT NULL)
CREATE TABLE b2 (blat2 VARCHAR(200) NOT NULL)
GO

INSERT b1
SELECT LEFT(AddressLine1, 5) AS blat1
FROM AdventureWorks.Person.Address

INSERT b2
SELECT AddressLine1 AS blat2
FROM AdventureWorks.Person.Address
GO

Hur kan man skriva om nedanstående fråga så att den blir snabbare (den tar ungefär sex minuter på min PC):

SELECT *
FROM b1
JOIN b2 ON
b2.blat2 LIKE b1.blat1 + '%'

Inga objekt-ändringar är tillåtna, dvs ingen indexering av tabellerna får göras.

Lösningen är att göra exakta jämförelser istället för ungefärliga. Dvs att använda "="-operatorn istället för "LIKE"-operatorn. Varför? Jo, därför att "LIKE"-operatorn gör att vi måste använda oss av en "NESTED LOOP" för att jämföra raderna. Dvs SQL Servers Query Processor (QP) måste titta på varje rad i den yttre tabellen i JOIN-operationen, och för varje rad i den yttre tabellen måste QP titta på varje rad i den inre tabellen för att jämföra data. Både b1 och b2 innehåller 19614 rader. Det är inga extrema datamängder, långt därifrån. För att köra ovanstående fråga måste QP titta på 19614 i b1, och för varje av dessa rader måste 19614 rader i b2 undersökas. Dvs 384 708 996 rader måste undersökas.

Lyckas vi istället använda en "="-operator kan QP använda en "MERGE" eller "HASH MATCH", vilket väsentligen reducerar antalet rader att titta på.

Min omskrivna fråga blir:

SELECT *
FROM b1
JOIN b2 ON
LEFT(b2.blat2,5) = b1.blat1

Det funkar därför att vi vet att b1.blat2 innehåller de första fem tecknen från b2.blat2. Tack vare den vetskapen kan frågan skrivas om, och köras på två sekunder. QP utför en "HASH MATCH" och antalet rader som måste undersökas för att utföra JOIN-operationen reduceras väsentligt.

Nedan ser du bilder av de estimerade planerna för de båda frågorna, och kan själv se skillnaden i estimerat antal rader för "NESTED LOOP" jämfört med "HASH MATCH" (Jämför "Estimated Number of Rows")

image 
SELECT * FROM b1 JOIN b2 ON b2.blat2 like b1.blat1 +'%'

image
SELECT * FROM b1 JOIN b2 ON left(b2.blat2,5) = b1.blat1

Intressant?
Andra bloggar om SQL Server, Optimering

Comments [0]   Kategorier: Optimering


Top Datorer bloggar
Bloggar.Topplista.se - topplistan med de b�sta bloggarna - l�gg till din blogg du ocks�!
BlogRankers.com
Bloggtoppen.se
Datorer
BloggRegistret.se




Total Posts: 14
This Year: 2
This Month: 0
This Week: 0
Comments: 65