Domanda MySQL: il modo più veloce per contare il numero di righe


In che modo contare un numero di righe dovrebbe essere più veloce in MySQL?

Questo:

SELECT COUNT(*) FROM ... WHERE ...

Oppure, l'alternativa:

SELECT 1 FROM ... WHERE ...

// and then count the results with a built-in function, e.g. in PHP mysql_num_rows()

Si potrebbe pensare che il primo metodo dovrebbe essere più veloce, poiché questo è chiaramente territorio del database e il motore del database dovrebbe essere più veloce di chiunque altro quando determina cose come questa internamente.


90
2018-02-20 21:59


origine


risposte:


Quando tu COUNT(*) prende gli indici delle colonne di conteggio, quindi sarà il miglior risultato. Mysql con MyISAM il motore memorizza effettivamente il conteggio delle righe, non esegue il conteggio di tutte le righe ogni volta che si tenta di contare tutte le righe. (basato sulla colonna della chiave primaria)

Usare PHP per contare le righe non è molto intelligente, perché devi inviare i dati da mysql a php. Perché farlo quando puoi ottenere lo stesso sul lato mysql?

Se la COUNT(*) è lento, dovresti correre EXPLAIN sulla query e controllare se gli indici sono realmente utilizzati e dove dovrebbero essere aggiunti.


Quello che segue non è il più veloce modo, ma c'è un caso, dove COUNT(*) non si adatta in modo corretto: quando inizi a raggruppare i risultati, puoi incappare in problemi, dove COUNT non conta davvero tutte le righe.

La soluzione è SQL_CALC_FOUND_ROWS. Questo viene solitamente utilizzato quando si selezionano le righe, ma è comunque necessario conoscere il numero totale di righe (ad esempio, per il paging). Quando selezioni le righe di dati, aggiungi semplicemente il SQL_CALC_FOUND_ROWS parola chiave dopo SELECT:

SELECT SQL_CALC_FOUND_ROWS [needed fields or *] FROM table LIMIT 20 OFFSET 0;

Dopo aver selezionato le righe necessarie, puoi ottenere il conteggio con questa singola query:

SELECT FOUND_ROWS();

FOUND_ROWS() deve essere chiamato immediatamente dopo la query di selezione dei dati.


In conclusione, tutto in realtà si riduce a quante voci hai e cosa c'è nell'istruzione WHERE. Dovresti davvero prestare attenzione a come vengono usati gli indici, quando ci sono molte righe (decine di migliaia, milioni e oltre).


101
2018-02-20 22:03



Grande domanda, grandi risposte. Ecco un modo rapido per echeggiare i risultati se qualcuno sta leggendo questa pagina e manca quella parte:

$counter = mysql_query("SELECT COUNT(*) AS id FROM table");
$num = mysql_fetch_array($counter);
$count = $num["id"];
echo("$count");

32
2017-12-31 12:12



Dopo aver parlato con i miei compagni di squadra, Ricardo ci ha detto che il modo più veloce è:

show table status like '<TABLE NAME>' \G

Ma devi ricordare che il risultato potrebbe non essere esatto.

Puoi usarlo anche da linea di comando:

$ mysqlshow --status <DATABASE> <TABLE NAME>

Maggiori informazioni: http://dev.mysql.com/doc/refman/5.7/en/show-table-status.html

E puoi trovare una discussione completa a mysqlperformanceblog


32
2017-08-27 13:06



Ho sempre capito che il seguito mi darà i tempi di risposta più rapidi.

SELECT COUNT(1) FROM ... WHERE ...

11
2018-02-20 22:01



Questa query (che è simile a quanto pubblicato bayuah) mostra un bel riepilogo di tutte le tabelle contate all'interno di un database: (versione semplificata di stored procedure di Ivan Cachicatari che consiglio vivamente).

SELECT TABLE_NAME AS 'Table Name', TABLE_ROWS AS 'Rows' FROM information_schema.TABLES WHERE TABLES.TABLE_SCHEMA = 'YOURDBNAME' AND TABLES.TABLE_TYPE = 'BASE TABLE';

Esempio:

+-----------------+---------+ | Table Name | Rows | +-----------------+---------+ | some_table | 10278 | | other_table | 995 |


10
2017-10-20 01:04



Se è necessario ottenere il conteggio dell'intero set di risultati, è possibile adottare il seguente approccio:

SELECT SQL_CALC_FOUND_ROWS * FROM table_name LIMIT 5;
SELECT FOUND_ROWS();

Questo non è normalmente più veloce dell'uso COUNT anche se si potrebbe pensare il contrario è perché esegue il calcolo internamente e non restituisce i dati all'utente, pertanto si sospetta il miglioramento delle prestazioni.

Fare queste due query è utile per l'impaginazione per ottenere i totali, ma non particolarmente per l'utilizzo WHERE clausole.


6
2017-11-12 12:29



Ho fatto alcuni benchmark per confrontare il tempo di esecuzione di COUNT(*) vs COUNT(id) (id è la chiave primaria della tabella - indicizzata).

Numero di prove:    10 * 1000 query

risultati:     COUNT(*) è più veloce del 7%

VISUALIZZA IL GRAFICO: benchmarkgraph

Il mio consiglio è di usare: SELECT COUNT(*) FROM table


3
2017-07-18 06:08



Gestivo tavoli per il governo tedesco con a volte 60 milioni di dischi.

E dovevamo sapere molte volte le righe totali.

Quindi noi programmatori di database abbiamo deciso che in ogni tabella si registra sempre il record in cui sono memorizzati i numeri dei record totali. Abbiamo aggiornato questo numero, a seconda delle righe INSERT o DELETE.

Abbiamo provato tutti gli altri modi. Questo è di gran lunga il modo più veloce.


2
2017-10-01 21:50



Forse potresti voler considerare di fare un SELECT max(Id) - min(Id) + 1. Funzionerà solo se i tuoi ID sono sequenziali e le righe non vengono cancellate. È comunque molto veloce.


1
2017-10-17 14:33