sql >> Databasteknik >  >> RDS >> Sqlserver

Effektivt sätt att få @@rowcount från en fråga med hjälp av row_number

Under årens lopp har en hög med utvecklarsvett lagts ner på att effektivt söka resultatuppsättningar. Ändå finns det inget svar – det beror på ditt användningsfall. En del av användningsfallet är att få din sida effektivt, en del är att räkna ut hur många rader som finns i en komplett resultatuppsättning. Så ursäkta om jag avviker lite till personsökning, men de två är ganska tätt sammankopplade i mitt sinne.

Det finns många strategier, varav de flesta är dåliga om du har någon form av datavolym och inte passar användningsfallet. Även om detta inte är en komplett lista, följer några av alternativen.....

Kör separat Count(*)

  • kör en separat fråga som gör en enkel "select count(*) from MyTable"
  • enkelt och lätt för ett litet bord
  • bra på en ofiltrerad stor tabell som antingen är smal eller har ett kompakt icke-klustrat index som du kan använda
  • bryts ner när du har en komplicerad WHERE/JOIN kriterier eftersom WHERE/JOIN körs två gånger är dyrt.
  • bryts ner på ett brett index eftersom antalet läsningar ökar.

Kombinera ROW_Number() OVER() och COUNT(1) OVER(PARTITION By 1)

  • Detta föreslogs av @RBarryYoung. Det har fördelen att det är enkelt att implementera och mycket flexibelt.
  • Nackdelen är att det finns många anledningar till att detta snabbt kan bli extremt dyrt.
  • Till exempel, i en DB som jag arbetar för närvarande finns det en mediatabell med cirka 6000 rader. Det är inte särskilt brett, har ett heltals klustrade PK och, såväl som ett kompakt unikt index. Ändå, en enkel COUNT(*) OVER(PARTITION BY 1) as TotalRows resulterar i ~12 000 läsningar. Jämför det med en enkel SELECT COUNT(*) FROM Media -- 12 läsningar. Wowzers.

Templariska tabeller / tabellvariabler

  • Det finns många strategier som tar en resultatuppsättning och infogar relevanta nycklar eller segment av resultat i tillfälliga tabeller/tabellvariabler.
  • För små/medelstora resultatuppsättningar kan detta ge fantastiska resultat.
  • Den här typen av strategi fungerar över nästan alla plattformar/versioner av SQL.
  • Det är också enkelt att använda en resultatuppsättning flera gånger (ganska ofta ett krav).
  • Nackdelen är när man arbetar med stora resultatuppsättningar ... att infoga några miljoner rader i en tillfällig tabell har en kostnad.
  • För att förstärka problemet kan trycket på TempDB vara en stor faktor i ett system med hög volym, och temporära tabeller fungerar effektivt i TempDB.

Gaussisk summa/dubbel radnummer

  • Den här idén bygger på delmängd av något matematikern Gauss kom på (hur man summerar en serie tal). Delmängden är hur man får radräkning från valfri punkt i tabellen.
  • Från en serie nummer (Row_Number() ) radantalet för 1 till N är (N + 1) - 1 . Mer förklaring i länkarna.
  • Formeln verkar som om den bara skulle vara N, men om du håller fast vid formeln händer det intressanta saker, du kan räkna ut radräkningen från en sida i mitten av tabellen.
  • Nettoresultatet är att du gör ROW_Number() OVER(Order by ID) och ROW_Number() OVER(Order by ID DESC) summera sedan de två talen och subtrahera 1.
  • Med min medietabell som exempel sjönk mina läsningar från 12 000 till cirka 75.
  • På en större sida har det slutat med att du upprepar data många många gånger, men förskjutningen i läsningar kan vara värt det.
  • Jag har inte testat detta på för många scenarier, så det kan falla isär i andra scenarier.

Överst (@n) / STÄLL IN RADANTAL

  • Detta är inte specifika strategier i sig, utan är optimeringar baserade på vad vi vet om frågeoptimeraren.
  • Kreativt användande av Top(@n) [top kan vara en variabel i SQL 2008] eller SET ROWCOUNT kan minska din arbetsuppsättning ... även om du drar en mittsida i en resultatuppsättning kan du fortfarande begränsa resultatet
  • Dessa idéer fungerar på grund av frågeoptimerarens beteende ...en service pack/snabbkorrigering kan ändra beteendet (men förmodligen inte).
  • I vissa fall kan SET ROWCOUNT vara lite korrekt
  • Denna strategi tar inte hänsyn till att få hela radantalet, bara gör personsökningen mer effektiv

Så vad ska en utvecklare göra?

Läs min gode man, läs. Här är några artiklar som jag har lutat mig mot...

Hoppas det hjälper.



  1. Oracle SQL-utvecklare:Fel - Testet misslyckades:Nätverksadaptern kunde inte upprätta anslutningen?

  2. MySQL Fråga om schemaläggning

  3. MySql SELECT AS - Lägg till alla fältnamn

  4. Hur man använder förberedda satser i frågor med en IN-sats i PHP