I årenes løb er der gået en bunke udviklersved ind i effektiv sidesøgning af resultatsæt. Alligevel er der intet svar - det afhænger af din brugssituation. En del af use casen er at få din side effektivt, en del er at finde ud af, hvor mange rækker der er i et komplet resultatsæt. Så undskyld, hvis jeg går lidt ind i personsøgning, men de to er temmelig tæt forbundet i mit sind.
Der er mange strategier, hvoraf de fleste er dårlige, hvis du har nogen form for datavolumen og ikke passer til brugssituationen. Selvom dette ikke er en komplet liste, er følgende nogle af mulighederne.....
Kør separat Count(*)
- kør en separat forespørgsel, der laver en simpel "vælg tælling(*) fra MinTabel"
- enkelt og nemt til et lille bord
- godt på en ufiltreret stor tabel, der enten er smal eller har et kompakt ikke-klynget indeks, som du kan bruge
- bryder sammen, når du har en kompliceret
WHERE/JOIN
kriterier, fordi du kørerWHERE/JOIN
to gange er dyrt. - nedbrydes på et bredt indeks, fordi antallet af læsninger stiger.
Kombiner ROW_Number() OVER()
og COUNT(1) OVER(PARTITION By 1)
- Dette blev foreslået af @RBarryYoung. Den har fordelen ved at være enkel at implementere og meget fleksibel.
- Den negative side er, at der er mange grunde til, at dette hurtigt kan blive ekstremt dyrt.
- For eksempel, i en DB, jeg arbejder i øjeblikket, er der en medie-tabel med omkring 6000 rækker. Den er ikke særlig bred, har et heltals-klyngede PK og et kompakt unikt indeks. Alligevel en simpel
COUNT(*) OVER(PARTITION BY 1) as TotalRows
resulterer i ~12.000 læsninger. Sammenlign det med en simpelSELECT COUNT(*) FROM Media
-- 12 læsninger. Wowzers.
Temperaturtabeller/tabelvariabler
- Der er masser af strategier, der tager et resultatsæt og indsætter relevante nøgler eller segmenter af resultater i midlertidige tabeller/tabelvariabler.
- For små/mellemstore resultatsæt kan dette give fantastiske resultater.
- Denne type strategi fungerer på tværs af næsten enhver platform/version af SQL.
- Det er også nemt at betjene et resultatsæt flere gange (temmelig ofte et krav).
- Den negative side er, når man arbejder med store resultatsæt ... det koster at indsætte et par millioner rækker i en midlertidig tabel.
- For at sammensætte problemet kan pres på TempDB være en stor faktor i et system med høj volumen, og midlertidige tabeller fungerer effektivt i TempDB.
Gaussisk sum/dobbelt rækkenummer
- Denne idé er afhængig af undersæt af noget matematikeren Gauss fandt ud af (hvordan man summerer en række tal). Undersættet er, hvordan man får rækkeantal fra ethvert punkt i tabellen.
- Fra en række tal (
Row_Number()
) rækkeantallet for 1 til N er(N + 1) - 1
. Mere forklaring i linkene. - Formlen ser ud til, at den kun vil være N, men hvis du holder dig til formlen, sker der interessante ting, du kan finde ud af rækkeantallet fra en side i midten af tabellen.
- Nettoresultatet er, at du gør
ROW_Number() OVER(Order by ID)
ogROW_Number() OVER(Order by ID DESC)
summer derefter de to tal og træk 1 fra. - Ved at bruge min medie-tabel som eksempel faldt mine læsninger fra 12.000 til omkring 75.
- På en større side er du endt med at gentage data mange gange, men forskydningen i læsninger kan være det værd.
- Jeg har ikke testet dette på for mange scenarier, så det kan falde fra hinanden i andre scenarier.
Top (@n) / INDSTIL RÆKKER
- Dette er ikke specifikke strategier i sig selv, men er optimeringer baseret på, hvad vi ved om forespørgselsoptimeringsværktøjet.
- Kreativt brug af Top(@n) [top kan være en variabel i SQL 2008] eller SET ROWCOUNT kan reducere dit arbejdssæt ... selvom du trækker en midterside af et resultatsæt, kan du stadig indsnævre resultatet
- Disse ideer fungerer på grund af forespørgselsoptimeringsadfærd ...en service pack/hotfix kan ændre adfærden (selv om det sandsynligvis ikke er).
- I visse tilfælde kan SET ROWCOUNT være en smule nøjagtigt
- Denne strategi tager ikke højde for det fulde antal rækker, den gør kun personsøgning mere effektiv
Så hvad skal en udvikler gøre?
Læs min gode mand, læs. Her er nogle artikler, som jeg har lænet mig op ad...
- En mere effektiv metode til at bladre gennem store resultatsæt
- Optimering af serversidesøgning - del I
- Optimering af serversidesøgning - del II
- Forklaring af den Gaussiske Sum
- Returnering af rangerede resultater med Microsoft SQL Server 2005
- ROW_NUMBER() OVER Ikke hurtigt nok med stort resultatsæt
- Hentning af de første N poster fra en SQL-forespørgsel
- Server Side Paging ved hjælp af SQL Server 2005
- Hvorfor er logiske læsninger for aggregerede vinduesfunktioner så høje?
Håber det hjælper.