Optimera SQL Server Full Text Search
Förord
Full Text Indexering är en suverän egenskap som kan lösa ett långtgående databas problem, nämligen det att söka igenom din SQL Server databas för textkolumner innehållande specifika ord eller fraser. Men eftersom sökmaskinen för Full Text är en separat komponent av SQL Server (den använder sig nämligen av Microsoft Search Engine), så kan det, med tanke på hur en Full Text sökning interagerar med SQL Server, bli uppkomsten till eventuella problem i prestandan.Innehåll
Optimera din SQL Server Full Text Search
Av Tony Bain
Full Text Search fungerar riktigt bra då du gör en sökning i en textkolumn och är intresserad av alla poster som matchar dina högt selektiva sökkriterier. Men en Full Text sökning sker vanligtvis i samband med andra SQL Server underlag, så som dem som är inkluderade i WHERE klausulen.
Låt oss t ex säga att du vill söka någonting som är till salu som har med beskrivningen ”baths” (badkar). Du är dessutom bara intresserad av ”flats” (våningar) som har badkar. Tabellens statistik visar:
Objekt | Antal objekt | Antal objekt med badkar
Houses | 800 000 | 330 000
Flats | 20 000 | 2 000
Apartments | 15 000 | 1 200
För att få fram resultaten bör du skriva SQL-satsen som följer:
SELECT *
FROM properties p
INNER JOIN containstable(properties, description, 'bath') t
ON p.PropertyID = t.[key]
WHERE p.type = 'flat'
Det är nu som Full Text börjar underprestera, och som jag sa tidigare så beror det på hur Microsoft Search Engine interagerar med SQL Server. Det som sker är att Search tjänsten blir tillfrågad att genomsöka katalogen efter poster som innehåller ordet ”bath”. De matchande posterna returneras till SQL Server som filtrerar ut posterna till att endast visa dem tio första posterna som innehåller ordet ”flat”.
Ett sätt att höja prestandan i det som sker i exemplet ovan skulle kunna vara genom att Search tjänsten returnerar posterna till Query Optimizer istället. I exemplet ovan är vi bara intresserade av de tio första posterna, men Search tjänsten returnerar 333 200 poster till Query Optimizer. Optimizern filtrerar då ut de tio första posterna som innehåller ordet ”flat”.
Det finns för närvarande ingen möjlighet att begränsa antalet poster som din Query Optimizer returnerar till SQL Servern, mer än genom att i kodningen skriva in parametern TOP_n_BY_RANK i ”containstable” funktionen (vilken vi skrev förut).
TOP_n_BY_RANK parametern i ”containstable” funktionen kan begränsa antalet poster som returneras till det antal som du anger. Se exemplet nedan och lägg märke till siffran som tillkommit.
SELECT *
FROM properties p
INNER JOIN containstable(properties, description, 'bath',10) t
ON p.PropertyID = t.[key]
WHERE p.type = 'flat'
Trots att det verkar som om detta räcker för att fylla våra behov, så kan det faktiskt hända att inga poster returneras alls. Det beror på att Search tjänsten tittar på TOP_n_BY RANK parametern innan posterna returneras till SQL Servern. Och det kan vara så att de tio första posterna som väljs ut och returneras till SQL Servern inte alls innehåller ordet ”flat”, vilket innebär att det inte finns några poster att filtrera ut.
För att vara ärlig så finns det inget elegant sätt att förbättra prestandan på. Du kan ju däremot dramatiskt förbättra SQL-satsernas prestanda genom att bädda in vissa textkoder i textkolumnerna. På så sätt kan du söka igenom både de inbäddade textkoderna samt kraven för de önskade resultaten. Det kan hjälpa till att minska ner antalet poster som returneras till SQL, samt förbättra en textsökande SQL-sats.
Om dina data t ex är:
PropertyID | Objekt | Beskrivning
1 | HOUSE | Big, Nice, Tidy, Shower, Kitchen
2 | FLAT | Small, Tidy, Shower, Bath, Gas
3 | HOUSE | Medium, Average Quality, Bath
......
uppdatera dem då till:
PropertyID | Objekt | Beskrivning
1 | HOUSE TYPEHOUSE | Big, Nice, Tidy, Shower, Kitchen
2 | FLAT TYPEFLAT | Small, Tidy, Shower, Bath, Gas
3 | HOUSE TYPEHOUSE | Medium, Average Quality, Bath
......
och då kan du skriva om din SQL-sats till följande:
SELECT top 10 *
FROM properties p
INNER JOIN containstable(properties,'"TYPEFLAT" and "bath"') t
ON p.PropertyID = t.[key]
WHERE p.type = 'flat'
I detta exempel returneras 2 000 poster till Query Optimizer och de 10 första posterna vidare till användaren. Det kan vara acceptabelt. Och om vi skriver in följande:
SELECT top 10 *
FROM properties p
INNER JOIN containstable(properties,'"TYPEHOUSE" and "bath"') t
ON p.PropertyID = t.[key]
WHERE p.type = 'house'
Här returneras 330 000 poster till Query Optimizer, vilket innebär att prestandan fortfarande inte är bra. Men nu när vi kan filtrera ut posterna i Search tjänsten innan de returneras till Query Optimizer, så kan vi ange antalet poster som ska returneras i TOP_n_BY_RANK parametern i containstabel-funktionen. Så om vi skriver om det blir det som följer:
SELECT *
FROM properties p
INNER JOIN containstable(properties,'"TYPEFLAT" and "bath"',10) t
ON p.PropertyID = t.[key]
WHERE p.type = 'flat'
Uppenbarligen vill du inte returnera ordet ”TYPEFLAT” till resultatlistan i din applikation, så slutresultatet av din SQL-sats bör bli:
SELECT PropertyID, Type, SubString(description, 9, 9 - LEN(description)) AS description
FROM properties p
INNER JOIN containstable(properties,'"TYPEFLAT" and "bath"',10) t
ON p.PropertyID = t.[key]
WHERE p.type = 'flat'
I detta exempel returneras bara 10 poster till Query Optimizer, så din prestanda bör ROCKA!
Det är ganska uppenbart att du bör använda triggers för att hålla kvar textkoden i textkolumnen, men arbetslasten som blir bör vara minimal jämfört med hastigheten på prestanda som du har tjänat in.
0 Kommentarer