sql >> Database teknologi >  >> RDS >> Sqlserver

Effektiv måde at få @@rowcount fra en forespørgsel ved hjælp af row_number

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ører WHERE/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 simpel SELECT 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) og ROW_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...

Håber det hjælper.



  1. Hvad er standardadgangskoden til Postgres

  2. Tjek den plads, der bruges af en tabel i SQL Server

  3. MySQL LIKE med json_extract

  4. Sådan repareres forældet oracle.sql.ArrayDescriptor, oracle.sql.STRUCT og oracle.sql.StructDescriptor