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

Un modo efficiente per ottenere @@rowcount da una query utilizzando row_number

Nel corso degli anni, un mucchio di sudore da parte degli sviluppatori è stato utilizzato per impaginare in modo efficiente set di risultati. Tuttavia, non c'è una risposta:dipende dal tuo caso d'uso. Parte del caso d'uso è ottenere la tua pagina in modo efficiente, parte è capire quante righe ci sono in un set di risultati completo. Mi scuso se mi allontano un po' nel paging, ma nella mia mente i due sono piuttosto accoppiati.

Esistono molte strategie, la maggior parte delle quali sono cattive se si dispone di qualsiasi tipo di volume di dati e non si adatta al caso d'uso. Anche se questo non è un elenco completo, di seguito sono riportate alcune delle opzioni.....

Esegui Count(*) separati

  • esegui una query separata che esegue un semplice "select count(*) from MyTable"
  • semplice e facile per un tavolino
  • buono su un tavolo grande non filtrato che è stretto o ha un indice compatto non in cluster che puoi utilizzare
  • si interrompe quando hai un complicato WHERE/JOIN criteri perché eseguendo il WHERE/JOIN due volte è costoso.
  • si scompone su un indice ampio perché il numero di letture aumenta.

Combina ROW_Number() OVER() e COUNT(1) OVER(PARTITION By 1)

  • Questo è stato suggerito da @RBarryYoung. Ha il vantaggio di essere semplice da implementare e molto flessibile.
  • Il lato negativo è che ci sono molte ragioni per cui questo può diventare estremamente costoso rapidamente.
  • Ad esempio, in un DB su cui sto lavorando c'è una tabella Media con circa 6000 righe. Non è particolarmente ampio, ha un PK in cluster intero e, oltre a un indice univoco compatto. Eppure, un semplice COUNT(*) OVER(PARTITION BY 1) as TotalRows risulta in circa 12.000 letture. Confrontalo con un semplice SELECT COUNT(*) FROM Media -- 12 letture. Wowzer.

Tabelle temporanee/Variabili di tabella

  • Ci sono molte strategie che prendono un set di risultati e inseriscono chiavi o segmenti di risultati rilevanti in tabelle temporanee/variabili di tabella.
  • Per i set di risultati di piccole/medie dimensioni questo può fornire ottimi risultati.
  • Questo tipo di strategia funziona su quasi tutte le piattaforme/versioni di SQL.
  • Anche l'operazione su un set di risultati più volte (molto spesso un requisito) è facile.
  • Il lato negativo è quando si lavora con set di risultati di grandi dimensioni... l'inserimento di alcuni milioni di righe in una tabella temporanea ha un costo.
  • Ad aggravare il problema, in un sistema ad alto volume la pressione su TempDB può essere un fattore determinante e le tabelle temporanee funzionano efficacemente in TempDB.

Somma gaussiana/Numero riga doppia

  • Questa idea si basa su sottoinsieme di qualcosa che il matematico Gauss ha scoperto (come sommare una serie di numeri). Il sottoinsieme è come ottenere il conteggio delle righe da qualsiasi punto della tabella.
  • Da una serie di numeri (Row_Number() ) il conteggio delle righe da 1 a N è (N + 1) - 1 . Maggiori spiegazioni nei link.
  • La formula sembra essere solo N, ma se ti attieni alla formula succedono cose interessanti, puoi calcolare il conteggio delle righe da una pagina al centro della tabella.
  • Il risultato netto è che fai ROW_Number() OVER(Order by ID) e ROW_Number() OVER(Order by ID DESC) quindi somma i due numeri e sottrai 1.
  • Utilizzando la mia tabella Media come esempio, le mie letture sono scese da 12.000 a circa 75.
  • In una pagina più grande hai finito per ripetere i dati molte volte, ma l'offset in letture potrebbe valerne la pena.
  • Non l'ho testato in troppi scenari, quindi potrebbe andare in pezzi in altri scenari.

Inizio (@n) / IMPOSTA NUMERO RIGA

  • Queste non sono strategie specifiche di per sé, ma sono ottimizzazioni basate su ciò che sappiamo su Query Optimizer.
  • Utilizzando in modo creativo Top(@n) [top può essere una variabile in SQL 2008] o SET ROWCOUNT può ridurre il tuo working set ... anche se stai tirando una pagina centrale di un set di risultati puoi comunque restringere il risultato
  • Queste idee funzionano grazie al comportamento di Query Optimizer ...un service pack/hotfix può modificare il comportamento (anche se probabilmente non è così).
  • In certi casi, SET ROWCOUNT può essere un po' preciso
  • Questa strategia non tiene conto del conteggio completo delle righe, ma rende solo il paging più efficiente

Quindi cosa deve fare uno sviluppatore?

Leggi mio brav'uomo, leggi. Ecco alcuni articoli su cui mi sono appoggiato...

Spero di esserti stato d'aiuto.