COUNT(*) OVER() Lentissimo

di il
4 risposte

COUNT(*) OVER() Lentissimo

Ciao a tutti!
vi scrivo per un problema a cui non riesco a venirne a capo.
Sto utilizzando fetch/next per paginare i dati su una vista con 80 milioni di record.
Questa vista è generata da 2 tabelle in join (una tabella anagrafica e una dedicata alle date di prenotazione) per un totale di circa 80 milioni di record.

La query (l'ho ridotta all'osso senza clausole where che comunque ci dovranno essere) impiega circa 12 secondi ad estrapolare una decina di record, mentre se rimuovo il COUNT(*) OVER() impiega 3 millisecondi.

SELECT CPR.CatalogProductID
,COUNT(*) OVER(ORDER BY CatalogProductID)
FROM View_2 AS CPR
WHERE [CONDIZIONI]
GROUP BY CPR.CatalogProductID
ORDER BY CPR.CatalogProductID ASC
OFFSET (@PageIndex - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY

Purtroppo mi serve anche il numero di record "originali" .
Come posso fare per ottimizzarla?

Grazie mille a tutti!

4 Risposte

  • Re: COUNT(*) OVER() Lentissimo

    Salve,
    direi che la problematica e' implicita nell'espressione, visto che, a prescindere dal paging impostato, OFFSET x ROWS FETCH NEXT y ROWS ONLY, che comunque richiede la proiezione completa del prodotto delle 80Mln righe con successivo filtro del paging applicato... tendenzialmente direi che a prescindedere dalla possibilita' del query optimizer di usare anche un solo indice per fare la veloce lookup di posizionamento sulla "prima" riga dell'ofset, viene comunque fatto un index scan su tutte le righe al fine di avere il risultato di quell'espressione di COUNT (*) OVER...

    Aaron consiglia anche soluzioni alternative, vedi https://stackoverflow.com/questions/12352471/getting-total-row-count-from-offset-fetch-next, che risultano comunque ovviamente pesanti in termini prestazionali...
    salutoni
    --
    Andrea
  • Re: COUNT(*) OVER() Lentissimo

    Altro truchetto: COUNT(*) richiede il caricamento dell'INTERO RECORD, ma che non serve! Basta un COUNT(1).

    Non so se l'engine e' abbastanza intelligente da NON CARICARE il record, ma far fare a lui il lavoro che dovremmo fare noi non e' molto utile
  • Re: COUNT(*) OVER() Lentissimo

    Salve @Migliorabile,
    mi spiace contraddirti ma questo e' uno dei miti da sfatare... vedi anche https://stackoverflow.com/questions/1221559/count-vs-count1-sql-server ma soprattutto https://www.mssqltips.com/sqlservertip/4460/sql-server-count-function-performance-comparison/ dove vengono mostrati anche i piani di esecuzione, come anche http://www.advancesharp.com/questions/160/sql-server---select-count-1-vs-select-count
    la problematica sorge solo se viene indicata una colonna nullable con valorizzazioni NULL presenti nel set, come indicato anche nei BOL...
    leggende metropolitane dure a morire a partire gia' da SQL7 ... prima, non saprei, ancora non lo usavo
    un salutone
    --
    Andrea
  • Re: COUNT(*) OVER() Lentissimo

    Ciao @asql e @Migliorabile,
    al momento i tempi di risposta rimangono più o meno gli stessi anche provando altre soluzioni come ad esempio il RowNumber ASC e DESC.
    Ho provato a fare anche il COUNT(1) ma il tempo è pressochè analogo.
    Ho provato ad applicare dei filtri (come [DATA] BETWEEN @A AND @B) e i tempi di risposta sono nell'ordine dei 3MS.. ma quando chiedo il count arrivo a 12-13 SEC.

    Credo (credo) che la soluzione sia quella di creare una vista di tutti i valori possibili raggruppandoli per parametri di ricerca e poi andando in qualche modo a "sommarli".

    Come applicare questo però rimane un mistero al momento!
    Grazie e se vi viene in mente qualche altro consiglio io sono ben accetto nel provarlo!
    Grazie ancora!!
Devi accedere o registrarti per scrivere nel forum
4 risposte