Cosa può velocizzare una query di conteggio SQL?


9

Quando si esegue una query SQL (aggregata) di conteggio, cosa può accelerare i tempi di esecuzione in questi 3 sistemi di database? Sono sicuro che molte cose potrebbero accelerarlo (hardware per uno), ma sono solo un DBA alle prime armi, quindi sono sicuro che riceverò alcune risposte qui. Ho migrato circa 157 milioni di righe in un database SQL Server e questa query impiega un'eternità. Ma nel mio database Netezza di origine, ci vogliono pochi secondi.

Per esempio:

Netezza 6:

SELECT COUNT(*) FROM DATABASENAME..MYTABLE

Oracle 11g:

SELECT COUNT(*) FROM MYTABLE

SQL Server 2012:

SELECT COUNT(*) FROM DATABASENAME.[dbo].[MYTABLE]


1
Devi farlo solo una volta o ripetutamente?
Jon Seigel,

@JonSeigel stiamo effettuando carichi incrementali e confrontiamo i record tra i sistemi di database ogni giorno per assicurarci che i conteggi si sommino. Così ripetutamente.
MacGyver,

Risposte:


10

Netezza è un'appliance progettata per eccellere nelle scansioni di tabelle di grandi dimensioni, quindi è per questo che stai ottenendo risultati così rapidi su quel sistema.

Per il tuo SQL Server, puoi velocizzare notevolmente il conteggio delle righe eseguendo una query dal DMV sys.dm_db_partition_stats.

SELECT s.name AS [Schema], o.name AS [Table], SUM(p.row_count) AS [RowCount]
FROM sys.dm_db_partition_stats p JOIN sys.objects o
ON p.object_id = o.object_id JOIN sys.schemas s
ON o.schema_id = s.schema_id
WHERE p.index_id < 2
AND o.object_id = object_id('MyTable')
GROUP BY o.name, s.name;

In un ambiente di transazione elevato, questo DMV non è garantito per essere preciso al 100%. Ma dalla tua domanda, sembra che tu stia solo facendo il conteggio delle righe per verificare ogni tabella dopo la migrazione, quindi questa query dovrebbe funzionare per te.


4
@Phil perché? Se esegui il ciclo tra le tabelle ed esegui un costoso SELECT COUNT (*) da ciascuna - quanto è preciso il primo risultato una volta che hai raggiunto l'ultima tabella?
Aaron Bertrand

1
Per chiarezza, Phil aveva detto: "L'uso del dizionario dei dati, che non fornisce risultati accurati al 100%, è un cattivo consiglio. A mio avviso, la risposta dovrebbe essere modificata per rimuovere il suggerimento o eliminata - ricorda che le persone cercano su Google tali risposte e ciecamente taglia e incolla ... "Concordo sul fatto che la dichiarazione di non responsabilità è importante (e ci sono presumibilmente alcuni casi limite in cui i metadati non restituiscono risultati sensati), non sono d'accordo sul fatto che l'uso delle viste dei metadati in generale sia un cattivo consiglio.
Aaron Bertrand

5

Ecco una soluzione di SQL Server che utilizza COUNT_BIGall'interno di una vista indicizzata. In questo modo otterrai un conteggio coerente a livello transazionale senza l'overhead delle scansioni di tabelle o indici e senza la necessità di spazio di archiviazione richiesto per quest'ultimo:

CREATE TABLE [dbo].[MyTable](id int);
GO

CREATE VIEW [dbo].[MyTableRowCount]
    WITH SCHEMABINDING
AS

    SELECT
        COUNT_BIG(*) AS TableRowCount
        FROM [dbo].[MyTable];
GO

CREATE UNIQUE CLUSTERED INDEX IX_MyTableRowCount
    ON [dbo].[MyTableRowCount](TableRowCount);
GO

SELECT
    TableRowCount
    FROM [dbo].[MyTableRowCount] WITH(NOEXPAND);

Ciò richiederà una singola scansione iniziale (non allontanarsi da questo) e aggiungere un po 'di sovraccarico alle manipolazioni dei dati della tabella incrementale. Se stai facendo grandi operazioni con molti dati (al contrario di molte piccole operazioni), penso che il sovraccarico delle modifiche dovrebbe essere trascurabile.


@SQLKiwi: come mai le letture sono bloccate prima del 2012? Bug di SQL Server?
Jon Seigel,

@JonSeigel - My $ 0,05: gli indici cluster normali sulla tabella normale creata offline applica un blocco Sch-M sulla tabella. Dal punto di vista, ovviamente non è necessario, ma ciò significa un'alterazione dell'operazione Crea indice per creare un caso speciale per la vista indicizzata, che è stato fatto per SQL2012. IMHO, ovviamente.
Fabricio Araujo,

3

In Oracle, un indice di albero binario su una colonna NOT NULL può essere utilizzato per rispondere a un COUNT (*). Nella maggior parte dei casi sarà più veloce di una SCANSIONE TABELLA COMPLETA perché gli indici sono generalmente più piccoli della loro tabella di base.

Tuttavia, un indice di albero binario regolare sarà ancora enorme con 157 Mrows. Se la tabella non viene aggiornata contemporaneamente (ad es. Solo processo di caricamento batch), è possibile utilizzare invece un indice bitmap.

L'indice bitmap più piccolo sarebbe qualcosa del genere:

CREATE BITMAP INDEX ix ON your_table(NULL);

Le voci nulle vengono prese in considerazione da un indice bitmap. L'indice risultante sarà minuscolo (20-30 8k blocchi per milione di righe) rispetto a un normale indice ad albero binario o alla tabella di base.

Il piano risultante dovrebbe mostrare le seguenti operazioni:

----------------------------------------------
| Id  | Operation                     | Name | 
----------------------------------------------
|   0 | SELECT STATEMENT              |      |
|   1 |  SORT AGGREGATE               |      |
|   2 |   BITMAP CONVERSION COUNT     |      |
|   3 |    BITMAP INDEX FAST FULL SCAN| IX   |
----------------------------------------------

Se la tabella viene aggiornata contemporaneamente, un indice bitmap con un valore univoco sarà un punto controverso e non dovrebbe essere utilizzato.


3

In Oracle, la query di conteggio semplice viene spesso eseguita scansionando un indice anziché l'intera tabella. L'indice deve essere un indice bitmap o definito su una colonna con vincolo NOT NULL. Per query più complesse che richiedono la scansione completa della tabella, è possibile utilizzare query parallele.

Per abilitare la query parallela (Enterprise Edition richiesta), è possibile utilizzare il suggerimento di Optimizer:

select /*+ PARALLEL(mytable, 12) */ count(*) from mytable;

O abilitare la query parallela per tutte le query sulla tabella:

alter table mytable parallel 12;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.