Ottieni conteggi record per tutte le tabelle nel database MySQL


347

C'è un modo per ottenere il conteggio delle righe in tutte le tabelle in un database MySQL senza eseguirne uno SELECT count()su ogni tabella?


1
Risposta estesa che è anche accurato per InnoDB: stackoverflow.com/questions/24707814/...
gwideman

1
SELECT count (table_name) FROM INFORMATION_SCHEMA.TABLES DOVE TABLE_SCHEMA = 'YOUR_DB' fornirà il numero di tabelle nel database
shasi kanth

Risposte:


416
SELECT SUM(TABLE_ROWS) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE TABLE_SCHEMA = '{your_db}';

Nota dai documenti però: per le tabelle InnoDB, il conteggio delle righe è solo una stima approssimativa utilizzata nell'ottimizzazione SQL. Dovrai utilizzare COUNT (*) per conteggi esatti (che è più costoso).


266
oppure, se lo desideri per ogni tabella: SELEZIONA table_name, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES DOVE TABLE_SCHEMA = '{your_db}';
TheSoftwareJedi

5
C'è un altro modo per ottenere table_row e table_name? Perché voglio un risultato esatto non una stima approssimativa. Grazie.
Krunal Shah,

3
@krunalshah, Questa è una delle restrizioni di InnoDB. Vedi dev.mysql.com/doc/refman/5.0/it/innodb-rest restrizioni.html, sezione Restrizioni sulle tabelle InnoDB, per maggiori informazioni. Puoi sempre usare un SELECT COUNT (*) FROM t, che tuttavia è molto più lento
Contrassegnare il

2
Jaitsu, no non lo è. count (*) (o più realisticamente count (id)) è ciò che mysql usa per contare le sue righe non è vero? In ogni caso, l'ho appena provato e ho ottenuto un numero maggiore per la chiamata count (), qualunque cosa valga la pena.
codygman,

2
SELEZIONA TABLE_NAME, SUM (TABLE_ROWS) N DA INFORMATION_SCHEMA.TABLES DOVE TABLE_SCHEMA = gruppo '{your_db}' di TABLE_NAME;
PiyusG,

175

Probabilmente puoi mettere qualcosa insieme al tavolo Tabelle . Non l'ho mai fatto, ma sembra che abbia una colonna per TABLE_ROWS e una per TABLE NAME .

Per ottenere righe per tabella, puoi utilizzare una query come questa:

SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';

4
C'è un altro modo per ottenere table_row e table_name? Perché voglio un risultato esatto non una stima approssimativa. Grazie.
Krunal Shah,

1
come ha detto Kuranl, questo restituisce solo una stima e probabilmente restituirà risultati diversi se eseguito un paio di volte
Kris,

Le tabelle con almeno ~ 250 record sembrano riportare un numero diverso di righe ogni volta che eseguo questa query.
Arthur,

Ops ... vorrei aver visto prima la parola "Stimato" ... come ieri! La risposta non dovrebbe essere respinta? Poiché OP non ha chiesto "stimato" e sembra sciocco pensare che potrebbe desiderare un preventivo. "preventivo" Potresti salvare ai maroon come me la mancanza del "preventivo"?
Kreeverp,

111

Come @Venkatramanan e altri ho trovato INFORMAZIONI_SCHEMA.TABLES inaffidabili (usando InnoDB, MySQL 5.1.44), dando conteggi di righe differenti ogni volta che lo eseguo anche su tabelle sospese. Ecco un modo relativamente confuso (ma flessibile / adattabile) di generare una grande istruzione SQL che puoi incollare in una nuova query, senza installare gemme e cose Ruby.

SELECT CONCAT(
    'SELECT "', 
    table_name, 
    '" AS table_name, COUNT(*) AS exact_row_count FROM `', 
    table_schema,
    '`.`',
    table_name, 
    '` UNION '
) 
FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema = '**my_schema**';

Produce output in questo modo:

SELECT "func" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.func UNION                         
SELECT "general_log" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.general_log UNION           
SELECT "help_category" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_category UNION       
SELECT "help_keyword" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_keyword UNION         
SELECT "help_relation" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_relation UNION       
SELECT "help_topic" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_topic UNION             
SELECT "host" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.host UNION                         
SELECT "ndb_binlog_index" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.ndb_binlog_index UNION 

Copia e incolla tranne l'ultimo UNION per ottenere un output piacevole come,

+------------------+-----------------+
| table_name       | exact_row_count |
+------------------+-----------------+
| func             |               0 |
| general_log      |               0 |
| help_category    |              37 |
| help_keyword     |             450 |
| help_relation    |             990 |
| help_topic       |             504 |
| host             |               0 |
| ndb_binlog_index |               0 |
+------------------+-----------------+
8 rows in set (0.01 sec)

2
Grazie, speravo di non dover installare plugin / gemme per ottenere conteggi esatti.
bradvido,

Richiede troppo tempo per essere eseguito in caso di un numero elevato di tabelle nel database.
ollamh,

1
aggiungi "seleziona * da (" all'inizio e ") come ordine di output per desc_row_count desc" alla fine della query generata dopo aver rimosso l'ultimo UNION per ottenere l'ordine in base al conteggio delle tabelle
Raghavendra,

Per escludere le visualizzazioni: WHERE table_schema = ' my_schema ' e TABLE_TYPE LIKE '% TABLE%'
Watson,

38

Corro solo:

show table status;

Questo ti darà il conteggio delle righe per OGNI tabella più un mucchio di altre informazioni. Prima usavo la risposta selezionata, ma è molto più semplice.

Non sono sicuro che funzioni con tutte le versioni, ma sto usando 5.5 con il motore InnoDB.


5
Sfortunatamente, se stai usando InnoDB, questo approccio soffre delle stesse inesattezze degli altri metodi sopra descritti. Ad esempio, ho una tabella InnoDB che ha circa 65.000 righe, ma questi metodi qui riportano che ha da 350.000 a oltre 780.000.
PeterToTheThird

Per un DB con poche righe, è abbastanza preciso (o, abbastanza preciso per le mie esigenze). Mi ha dato 1086 righe per una tabella che COUNT (*) ha riportato 904 righe.
Magne,

Di gran lunga la migliore risposta. Uso InnoDB ma ho solo bisogno di un comando rapido per conoscere l'ordine di grandezza.
Nemo,

Seriamente, vorrei che questo fosse accettato. Non usare InnoDB e mi dà la risposta esatta.
Kolob Canyon,

1
Il numero di righe non è preciso ma "Auto_increment" può fornirti un numero preciso se non hai eliminato alcuna riga da tali tabelle.
Peter T.

13
 SELECT TABLE_NAME,SUM(TABLE_ROWS) 
 FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_SCHEMA = 'your_db' 
 GROUP BY TABLE_NAME;

Questo è tutto ciò di cui hai bisogno.


1
produce righe di tabella stimate - confronta con "mysql_num_rows ($ tableresult)"
Kreeverp

1
questa è la risposta migliore in realtà! Anche il più semplice da eseguire da mysql cli:mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
loretoparisi

11

Questa procedura memorizzata elenca le tabelle, conta i record e produce un numero totale di record alla fine.

Per eseguirlo dopo aver aggiunto questa procedura:

CALL `COUNT_ALL_RECORDS_BY_TABLE` ();

-

La procedura:

DELIMITER $$

CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `COUNT_ALL_RECORDS_BY_TABLE`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE TNAME CHAR(255);

DECLARE table_names CURSOR for 
    SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE();

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN table_names;   

DROP TABLE IF EXISTS TCOUNTS;
CREATE TEMPORARY TABLE TCOUNTS 
  (
    TABLE_NAME CHAR(255),
    RECORD_COUNT INT
  ) ENGINE = MEMORY; 


WHILE done = 0 DO

  FETCH NEXT FROM table_names INTO TNAME;

   IF done = 0 THEN
    SET @SQL_TXT = CONCAT("INSERT INTO TCOUNTS(SELECT '" , TNAME  , "' AS TABLE_NAME, COUNT(*) AS RECORD_COUNT FROM ", TNAME, ")");

    PREPARE stmt_name FROM @SQL_TXT;
    EXECUTE stmt_name;
    DEALLOCATE PREPARE stmt_name;  
  END IF;

END WHILE;

CLOSE table_names;

SELECT * FROM TCOUNTS;

SELECT SUM(RECORD_COUNT) AS TOTAL_DATABASE_RECORD_CT FROM TCOUNTS;

END

8

Modo semplice:

SELECT
  TABLE_NAME, SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{Your_DB}'
GROUP BY TABLE_NAME;

Esempio di risultato:

+----------------+-----------------+
| TABLE_NAME     | SUM(TABLE_ROWS) |
+----------------+-----------------+
| calls          |            7533 |
| courses        |             179 |
| course_modules |             298 |
| departments    |              58 |
| faculties      |             236 |
| modules        |             169 |
| searches       |           25423 |
| sections       |             532 |
| universities   |              57 |
| users          |           10293 |
+----------------+-----------------+

4

C'è un po 'di un trucco / soluzione per questo problema di stima.

Auto_Increment: per qualche motivo questo restituisce un conteggio delle righe molto più accurato per il database se si dispone di un incremento automatico impostato sulle tabelle.

Trovato questo durante l'esplorazione del motivo per cui le informazioni sulla tabella mostra non corrispondevano ai dati effettivi.

SELECT
table_schema 'Database',
SUM(data_length + index_length) AS 'DBSize',
SUM(TABLE_ROWS) AS DBRows,
SUM(AUTO_INCREMENT) AS DBAutoIncCount
FROM information_schema.tables
GROUP BY table_schema;


+--------------------+-----------+---------+----------------+
| Database           | DBSize    | DBRows  | DBAutoIncCount |
+--------------------+-----------+---------+----------------+
| Core               |  35241984 |   76057 |           8341 |
| information_schema |    163840 |    NULL |           NULL |
| jspServ            |     49152 |      11 |            856 |
| mysql              |   7069265 |   30023 |              1 |
| net_snmp           |  47415296 |   95123 |            324 |
| performance_schema |         0 | 1395326 |           NULL |
| sys                |     16384 |       6 |           NULL |
| WebCal             |    655360 |    2809 |           NULL |
| WxObs              | 494256128 |  530533 |        3066752 |
+--------------------+-----------+---------+----------------+
9 rows in set (0.40 sec)

È quindi possibile utilizzare facilmente PHP o qualsiasi altra cosa per restituire il massimo delle 2 colonne di dati per fornire la "migliore stima" per il conteggio delle righe.

vale a dire

SELECT
table_schema 'Database',
SUM(data_length + index_length) AS 'DBSize',
GREATEST(SUM(TABLE_ROWS), SUM(AUTO_INCREMENT)) AS DBRows
FROM information_schema.tables
GROUP BY table_schema;

L'incremento automatico sarà sempre +1 * (conteggio delle tabelle) di righe, ma anche con 4.000 tabelle e 3 milioni di righe, è preciso al 99,9%. Molto meglio delle righe stimate.

Il bello di questo è che i conteggi delle righe restituiti in performance_schema vengono cancellati anche per te, perché il più grande non funziona su null. Questo potrebbe essere un problema se non ci sono tabelle con incremento automatico.


3

Puoi provare questo. Funziona bene per me.

SELECT IFNULL(table_schema,'Total') "Database",TableCount 
FROM (SELECT COUNT(1) TableCount,table_schema 
      FROM information_schema.tables 
      WHERE table_schema NOT IN ('information_schema','mysql') 
      GROUP BY table_schema WITH ROLLUP) A;

2

Se si utilizza il database information_schema, è possibile utilizzare questo codice mysql (la parte in cui la query non mostra le tabelle che hanno un valore null per le righe):

SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0

1

La query seguente produce una query (nother) che otterrà il valore di count (*) per ogni tabella, da ogni schema, elencato in information_schema.tables. L'intero risultato della query mostrato qui - tutte le righe unite - comprende un'istruzione SQL valida che termina con un punto e virgola - nessuna 'unione' penzolante. L'unione penzolante viene evitata mediante l'uso di un'unione nella query seguente.

select concat('select "', table_schema, '.', table_name, '" as `schema.table`,
                          count(*)
                 from ', table_schema, '.', table_name, ' union ') as 'Query Row'
  from information_schema.tables
 union
 select '(select null, null limit 0);';

1

Questo è ciò che faccio per ottenere il conteggio effettivo (non utilizzare lo schema)

È più lento ma più preciso.

È un processo in due fasi

  1. Ottieni un elenco di tabelle per il tuo db. Puoi ottenerlo usando

    mysql -uroot -p mydb -e "show tables"
  2. Crea e assegna l'elenco di tabelle alla variabile array in questo script bash (separato da un singolo spazio proprio come nel codice seguente)

    array=( table1 table2 table3 )
    
    for i in "${array[@]}"
    do
        echo $i
        mysql -uroot mydb -e "select count(*) from $i"
    done
  3. Eseguirlo:

    chmod +x script.sh; ./script.sh

1

Un'altra opzione: per non InnoDB utilizza i dati di information_schema.TABLES (poiché è più veloce), per InnoDB - selezionare count (*) per ottenere il conteggio accurato. Inoltre ignora le visualizzazioni.

SET @table_schema = DATABASE();
-- or SET @table_schema = 'my_db_name';

SET GROUP_CONCAT_MAX_LEN=131072;
SET @selects = NULL;

SELECT GROUP_CONCAT(
        'SELECT "', table_name,'" as TABLE_NAME, COUNT(*) as TABLE_ROWS FROM `', table_name, '`'
        SEPARATOR '\nUNION\n') INTO @selects
  FROM information_schema.TABLES
  WHERE TABLE_SCHEMA = @table_schema
        AND ENGINE = 'InnoDB'
        AND TABLE_TYPE = "BASE TABLE";

SELECT CONCAT_WS('\nUNION\n',
  CONCAT('SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND ENGINE <> "InnoDB" AND TABLE_TYPE = "BASE TABLE"'),
  @selects) INTO @selects;

PREPARE stmt FROM @selects;
EXECUTE stmt USING @table_schema;
DEALLOCATE PREPARE stmt;

Se il tuo database ha molte tabelle InnoDB di grandi dimensioni, il conteggio di tutte le righe può richiedere più tempo.


0

Ecco come conto le TABELLE e TUTTI I REGISTRI usando PHP:

$dtb = mysql_query("SHOW TABLES") or die (mysql_error());
$jmltbl = 0;
$jml_record = 0;
$jml_record = 0;

while ($row = mysql_fetch_array($dtb)) { 
    $sql1 = mysql_query("SELECT * FROM " . $row[0]);            
    $jml_record = mysql_num_rows($sql1);            
    echo "Table: " . $row[0] . ": " . $jml_record record . "<br>";      
    $jmltbl++;
    $jml_record += $jml_record;
}

echo "--------------------------------<br>$jmltbl Tables, $jml_record > records.";

Perché non usi count (*) se ignorerai i dati?
Svetoslav Marinov

0

Il poster ha voluto contare le righe senza contare, ma non ha specificato quale motore di tabella. Con InnoDB, conosco solo un modo, che è contare.

Ecco come raccolgo le mie patate:

# Put this function in your bash and call with:
# rowpicker DBUSER DBPASS DBNAME [TABLEPATTERN]
function rowpicker() {
    UN=$1
    PW=$2
    DB=$3
    if [ ! -z "$4" ]; then
        PAT="LIKE '$4'"
        tot=-2
    else
        PAT=""
        tot=-1
    fi
    for t in `mysql -u "$UN" -p"$PW" "$DB" -e "SHOW TABLES $PAT"`;do
        if [ $tot -lt 0 ]; then
            echo "Skipping $t";
            let "tot += 1";
        else
            c=`mysql -u "$UN" -p"$PW" "$DB" -e "SELECT count(*) FROM $t"`;
            c=`echo $c | cut -d " " -f 2`;
            echo "$t: $c";
            let "tot += c";
        fi;
    done;
    echo "total rows: $tot"
}

A questo proposito non sto affermando altro che questo è un modo davvero brutto ma efficace per ottenere quante righe esistono in ogni tabella nel database indipendentemente dal motore della tabella e senza la necessità di disporre dell'autorizzazione per installare le stored procedure e senza la necessità di installare rubino o php. Sì, è arrugginito. Sì, conta. count (*) è preciso.


0

Sulla base della risposta di @ Nathan sopra, ma senza la necessità di "rimuovere l'unione finale" e con l'opzione per ordinare l'output, utilizzo il seguente SQL. Genera un'altra istruzione SQL che quindi esegue:

select CONCAT( 'select * from (\n', group_concat( single_select SEPARATOR ' UNION\n'), '\n ) Q order by Q.exact_row_count desc') as sql_query
from (
    SELECT CONCAT(
        'SELECT "', 
        table_name, 
        '" AS table_name, COUNT(1) AS exact_row_count
        FROM `', 
        table_schema,
        '`.`',
        table_name, 
        '`'
    ) as single_select
    FROM INFORMATION_SCHEMA.TABLES 
    WHERE table_schema = 'YOUR_SCHEMA_NAME'
      and table_type = 'BASE TABLE'
) Q 

È necessario un valore sufficientemente grande della group_concat_max_lenvariabile del server, ma da MariaDb 10.2.4 dovrebbe essere impostato automaticamente su 1M.


0

Il codice sottostante genera la query di selezione per tutti i racconti. Basta eliminare l'ultimo "UNION ALL" selezionare tutti i risultati e incollare una nuova finestra di query per l'esecuzione.

SELECT 
concat('select ''', table_name ,''' as TableName, COUNT(*) as RowCount from ' , table_name , ' UNION ALL ')  as TR FROM
information_schema.tables where 
table_schema = 'Database Name'

-1

Se vuoi i numeri esatti, usa il seguente script ruby. Hai bisogno di Ruby e RubyGems.

Installa le seguenti gemme:

$> gem install dbi
$> gem install dbd-mysql

File: count_table_records.rb

require 'rubygems'
require 'dbi'

db_handler = DBI.connect('DBI:Mysql:database_name:localhost', 'username', 'password')

# Collect all Tables
sql_1 = db_handler.prepare('SHOW tables;')
sql_1.execute
tables = sql_1.map { |row| row[0]}
sql_1.finish

tables.each do |table_name|
  sql_2 = db_handler.prepare("SELECT count(*) FROM #{table_name};")
  sql_2.execute
  sql_2.each do |row|
    puts "Table #{table_name} has #{row[0]} rows."
  end
  sql_2.finish
end

db_handler.disconnect

Torna alla riga di comando:

$> ruby count_table_records.rb

Produzione:

Table users has 7328974 rows.

-4

Se conosci il numero di tabelle e i loro nomi e supponendo che ciascuno abbia le chiavi primarie, puoi usare un cross join in combinazione con COUNT(distinct [column])per ottenere le righe che provengono da ogni tabella:

SELECT 
   COUNT(distinct t1.id) + 
   COUNT(distinct t2.id) + 
   COUNT(distinct t3.id) AS totalRows
FROM firstTable t1, secondTable t2, thirdTable t3;

Ecco un esempio di violino SQL .

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.