sql >> Database >  >> RDS >> Sqlserver

Efficiënte manier om @@rowcount uit een query te halen met row_number

In de loop der jaren is er een hoop ontwikkelaarszweet gestoken in het efficiënt pagineren van resultatensets. Toch is er niet één antwoord - het hangt af van uw gebruiksscenario. Een deel van de use case is om uw pagina efficiënt te krijgen, een deel is uitzoeken hoeveel rijen er in een complete resultatenset zitten. Dus sorry als ik een beetje afdwaal in paging, maar de twee zijn behoorlijk nauw met elkaar verbonden in mijn gedachten.

Er zijn veel strategieën, waarvan de meeste slecht zijn als je een soort datavolume hebt en niet in de use case passen. Hoewel dit geen volledige lijst is, volgen hier enkele van de opties.....

Voer aparte Count(*) uit

  • voer een aparte query uit die een simpele "select count(*) from MyTable" doet
  • eenvoudig en gemakkelijk voor een kleine tafel
  • goed voor een ongefilterde grote tabel die smal is of een compacte niet-geclusterde index heeft die u kunt gebruiken
  • gaat kapot als je een ingewikkelde WHERE/JOIN . hebt criteria omdat het uitvoeren van de WHERE/JOIN twee keer is duur.
  • breekt af op een brede index omdat het aantal leesbewerkingen omhoog gaat.

Combineer ROW_Number() OVER() en COUNT(1) OVER(PARTITION By 1)

  • Dit werd voorgesteld door @RBarryYoung. Het heeft het voordeel dat het eenvoudig te implementeren en zeer flexibel is.
  • De keerzijde is dat er veel redenen zijn waarom dit snel extreem duur kan worden.
  • Bijvoorbeeld, in een DB waar ik momenteel aan werk, is er een Media-tabel met ongeveer 6000 rijen. Het is niet bijzonder breed, heeft een geheel getal geclusterde PK en, evenals een compacte unieke index. Toch een simpele COUNT(*) OVER(PARTITION BY 1) as TotalRows resulteert in ~ 12.000 leest. Vergelijk dat met een simpele SELECT COUNT(*) FROM Media -- 12 leest. Wowzers.

Temptabellen / Tabelvariabelen

  • Er zijn veel strategieën die een resultatenset gebruiken en relevante sleutels of segmenten van resultaten invoegen in tijdelijke tabellen/tabelvariabelen.
  • Voor kleine/middelgrote resultaatsets kan dit geweldige resultaten opleveren.
  • Dit type strategie werkt op bijna elk platform/versie van SQL.
  • Meerdere keren op een resultatenset werken (vaak een vereiste) is ook eenvoudig.
  • De keerzijde is dat wanneer u met grote resultatensets werkt ... het invoegen van een paar miljoen rijen in een tijdelijke tabel kosten met zich meebrengt.
  • Om het probleem nog groter te maken, in een hoog volume kan de systeemdruk op TempDB een behoorlijke factor zijn, en tijdelijke tabellen werken effectief in TempDB.

Gaussiaanse som / dubbel rijnummer

  • Dit idee is gebaseerd op subset van iets waar de wiskundige Gauss achter kwam (hoe een reeks getallen op te tellen). De subset is hoe u het aantal rijen kunt krijgen vanaf elk punt in de tabel.
  • Van een reeks getallen (Row_Number() ) het aantal rijen voor 1 tot N is (N + 1) - 1 . Meer uitleg in de links.
  • De formule lijkt uit te komen op slechts N, maar als je je aan de formule houdt, gebeuren er interessante dingen, dan kun je het aantal rijen berekenen vanaf een pagina in het midden van de tabel.
  • Het netto resultaat is dat je ROW_Number() OVER(Order by ID) doet en ROW_Number() OVER(Order by ID DESC) tel dan de twee getallen op en trek 1 af.
  • Als ik mijn Media-tabel als voorbeeld gebruikte, daalden mijn leesresultaten van 12.000 naar ongeveer 75.
  • Op een grotere pagina heb je gegevens vaak herhaald, maar de verschuiving in het lezen kan de moeite waard zijn.
  • Ik heb dit niet in te veel scenario's getest, dus het kan in andere scenario's uit elkaar vallen.

Boven (@n) / ROWCOUNT INSTELLEN

  • Dit zijn op zich geen specifieke strategieën, maar optimalisaties op basis van wat we weten over de query-optimizer.
  • Creatief gebruik van Top(@n) [top kan een variabele zijn in SQL 2008] of SET ROWCOUNT kan uw werkset verkleinen ... zelfs als u een middelste pagina van een resultatenset trekt, kunt u het resultaat nog verkleinen
  • Deze ideeën werken vanwege het gedrag van de queryoptimalisatie ... een servicepack/hotfix kan het gedrag veranderen (hoewel waarschijnlijk niet).
  • In bepaalde gevallen kan SET ROWCOUNT een beetje nauwkeurig zijn
  • Deze strategie houdt geen rekening met het verkrijgen van het volledige aantal rijen, maar maakt paging alleen efficiënter

Dus wat moet een ontwikkelaar doen?

Lees mijn goede man, lees. Hier zijn enkele artikelen waarop ik heb geleund...

Ik hoop dat dat helpt.



  1. Oracle-verbindingen verbroken in SSIS na het verwijderen van de 32-bits versie van de Oracle-client

  2. Update met parameter met behulp van de permanente bibliotheek van de kamer

  3. gem install pg werkt niet op OSX Lion

  4. Hamming-afstand op binaire strings in SQL