Perché il conteggio (*) è lento, quando spiegare conosce la risposta?


14

Questa domanda: select count(*) from planner_eventrichiede molto tempo per essere eseguita - così a lungo, ho rinunciato e l'ho ucciso prima che finisse. Tuttavia, quando corro explain select count(*) from planner_event, posso vedere una colonna nell'output con il numero di righe (14m).

Come mai spiegare può ottenere immediatamente il numero di righe, ma il conteggio (*) richiede molto tempo per l'esecuzione?


COUNT (*) senza una causa WHERE provocherà una scansione della tabella sul motore InnoDB. MyISAM può recapitare il conteggio direttamente perché COUNT viene memorizzato nel file de header dalla tabella.
Raymond Nijland,

Risposte:


16

Spiega sta utilizzando le statistiche raccolte in precedenza (utilizzate da Query Optimizer). Fare una select count(*)lettura OGNI blocco di dati.

Ecco un modo economico per ottenere un conteggio di righe stimato:

select TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='planner_event';

Anche se lo facessi select count(id), potrebbe volerci molto tempo, a meno che tu non abbia un indice secondario attivo id(anche supponendo che idsia un PRIMARY KEY). Poiché tutti i dati (inclusi i dati di riga) sono archiviati negli indici B-Tree, l'esecuzione di a select count(PK_COLUMN)è ancora una quantità considerevole di IO (è necessario leggere tutte le pagine di dati). Se hai un indice secondario sul campo PK, sarà in grado di eseguire meno IO per eseguire un conteggio.


I_S.TABLES ti dà lo stesso preventivo che EXPLAINti dà.
Rick James,

La query non è presente AND TABLE_SCHEMA='my_database', altrimenti si otterranno più risultati se si dispone di una tabella con lo stesso nome in un altro database.
CZ

3

Spiega ottiene il numero da alcune "statistiche" che vengono utilizzate per stimare le cose per l'ottimizzatore. Quel numero può essere tutt'altro che corretto - a volte vedo che è più di un fattore 2 (superiore o inferiore) rispetto al valore esatto.

L'esecuzione di COUNT(*)una tabella InnoDB deve eseguire la scansione della tabella per evitare che i record errati che sono occupati vengano inseriti / eliminati da altre connessioni ma non ancora "impegnati". In realtà, è abbastanza buono fare una scansione completa su alcuni indici, non necessariamente sull'intera tabella (che contiene il PRIMARY KEY).

Quanta RAM hai? Qual è il valore di innodb_buffer_pool_size? Potrebbe essere utile se questo fosse circa il 70% della RAM.

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.