Una risposta letteralmente folle, ma se hai un qualche tipo di sistema di replica impostato (per un sistema con un miliardo di righe, spero che tu lo faccia), puoi usare uno stimatore approssimativo (come MAX(pk)
), dividere quel valore per il numero di slave hai eseguito diverse query in parallelo.
Per la maggior parte, partizioneresti le query tra gli slave in base alla chiave migliore (o alla chiave primaria immagino), in modo tale (useremo 250000000 come le nostre righe / slave):
-- First slave
SELECT COUNT(pk) FROM t WHERE pk < 250000000
-- Ith slave where 2 <= I <= N - 1
SELECT COUNT(pk) FROM t WHERE pk >= I*250000000 and pk < (I+1)*250000000
-- Last slave
SELECT COUNT(pk) FROM t WHERE pk > (N-1)*250000000
Ma hai bisogno solo di SQL. Che busto. Ok, allora diciamo che sei un sadomasochista. Sul master (o slave più vicino) molto probabilmente avresti bisogno di creare una tabella per questo:
CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)
Quindi invece di avere solo i selettori in esecuzione nei tuoi schiavi, dovresti fare un inserto, simile a questo:
INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)
È possibile che si verifichino problemi con gli slave che scrivono su una tabella del master. Potrebbe essere necessario ottenere ancora più sadici, voglio dire, creativo:
-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)
Alla fine dovresti avere uno slave che esiste per ultimo nel percorso attraversato dal grafico di replica, rispetto al primo slave. Lo slave dovrebbe ora avere tutti gli altri valori del contatore e dovrebbe avere i propri valori. Ma quando hai finito, probabilmente ci sono delle righe aggiunte, quindi dovresti inserirne un altro per compensare il pk massimo registrato nella tua counter_table e il pk massimo corrente.
A quel punto, dovresti fare una funzione aggregata per capire quali sono le righe totali, ma è più facile dato che le eseguiresti al massimo sul "numero di slave che hai e cambi".
Se ti trovi nella situazione in cui hai tabelle separate negli slave, puoi UNION
ottenere tutte le file di cui hai bisogno.
SELECT SUM(cnt) FROM (
SELECT * FROM counter_table_slave_1
UNION
SELECT * FROM counter_table_slave_2
UNION
...
)
O sai, sii un po 'meno pazzo e migra i tuoi dati su un sistema di elaborazione distribuito, o magari usa una soluzione di Data Warehousing (che ti darà un fantastico scricchiolio dei dati anche in futuro).
Nota, questo dipende da quanto è impostata la tua replica. Poiché il collo di bottiglia primario sarà molto probabilmente l'archiviazione persistente, se si dispone di memoria grezza o archivi di dati scarsamente separati con un forte rumore del vicino, questo probabilmente ti farà rallentare piuttosto che aspettare un singoloSELECT COUNT(*) ...
Ma se hai una buona replica, allora i tuoi guadagni di velocità dovrebbero essere direttamente correlati al numero o agli slave. In effetti, se sono necessari 10 minuti per eseguire la query di conteggio da solo e si dispone di 8 slave, si ridurrebbe il tempo a meno di un paio di minuti. Forse un'ora per appianare i dettagli di questa soluzione.
Certo, non otterrai mai una risposta incredibilmente accurata poiché questa soluzione distribuita introduce un po 'di tempo in cui le righe possono essere eliminate e inserite, ma puoi provare a ottenere un blocco distribuito di righe nella stessa istanza e ottenere un conteggio preciso delle righe nella tabella per un momento particolare nel tempo.
In realtà, questo sembra impossibile, dal momento che sei praticamente bloccato con una soluzione solo SQL, e non penso che ti sia stato fornito un meccanismo per eseguire una query frammentata e bloccata su più slave, all'istante. Forse se avessi il controllo del file di registro di replica ... il che significa che avresti letteralmente fatto girare gli schiavi per questo scopo, che è senza dubbio più lento della semplice esecuzione della query di conteggio su una singola macchina.
Quindi ci sono i miei due penny del 2013.