Obtenga recuentos de registros para todas las tablas en la base de datos MySQL

347

¿Hay alguna manera de obtener el recuento de filas en todas las tablas en una base de datos MySQL sin ejecutar un SELECT count()en cada tabla?

marca
fuente
1
Respuesta extendida que también es precisa para InnoDB: stackoverflow.com/questions/24707814/…
gwideman
1
SELECT count (table_name) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'YOUR_DB' le dará el número de tablas en su base de datos
shasi kanth

Respuestas:

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

Sin embargo , tenga en cuenta los documentos: para las tablas InnoDB, el recuento de filas es solo una estimación aproximada utilizada en la optimización de SQL. Tendrá que usar COUNT (*) para conteos exactos (que es más costoso)

Odia_
fuente
266
o, si desea para cada tabla: SELECCIONE nombre_tabla, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}';
TheSoftwareJedi
55
¿Hay alguna otra forma de obtener table_row y table_name? Porque quiero un resultado exacto, no una estimación aproximada. Gracias.
Krunal Shah
3
@krunalshah, esta es una de las restricciones de InnoDB. Consulte dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html , sección Restricciones en las tablas de InnoDB, para obtener más información. Siempre puedes usar un SELECT COUNT (*) FROM t, que, sin embargo, es mucho más lento
Marcado
2
Jaitsu, no, no lo es. count (*) (o más realista count (id)) es lo que mysql usa para contar sus filas, ¿no? En cualquier caso, solo lo probé y obtuve un número mayor para la llamada count (), lo que sea que valga la pena.
codygman
2
SELECCIONE TABLE_NAME, SUM (TABLE_ROWS) N FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}' grupo por TABLE_NAME;
PiyusG
175

Probablemente puedas juntar algo con la tabla Tablas . Nunca lo he hecho, pero parece que tiene una columna para TABLE_ROWS y una para TABLE NAME .

Para obtener filas por tabla, puede usar una consulta como esta:

SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';
gpojd
fuente
44
¿Hay alguna otra forma de obtener table_row y table_name? Porque quiero un resultado exacto, no una estimación aproximada. Gracias.
Krunal Shah
1
como se mencionó kuranl Esto devuelve sólo una estimación y probablemente devolver resultados diferentes cuando se ejecuta un par de veces
Kris
Las tablas con al menos ~ 250 registros parecen informar un número diferente de filas cada vez que ejecuto esta consulta.
Arthur
Ooops ... desearía haber visto la palabra "Estimado" de antemano ... ¡como ayer! ¿No se debe rechazar la respuesta? Como OP no pidió "estimado" y parece una tontería pensar que puede querer un estimado. "estimación" ¿Podría salvar a los cimarrones como yo de perder la "estimación"?
Kreeverp
111

Al igual que @Venkatramanan y otros, encontré que INFORMATION_SCHEMA.TABLES no es confiable (usando InnoDB, MySQL 5.1.44), dando diferentes recuentos de filas cada vez que lo ejecuto incluso en tablas inactivas. Aquí hay una forma relativamente hacky (pero flexible / adaptable) de generar una gran declaración SQL que puede pegar en una nueva consulta, sin instalar gemas y cosas de 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 resultados como este:

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 

Copie y pegue, excepto la última UNION para obtener una salida agradable como,

+------------------+-----------------+
| 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)
Nathan
fuente
2
Gracias, esperaba no tener que instalar ningún complemento / gema para obtener recuentos exactos.
bradvido
Tarda demasiado en ejecutarse en caso de un gran número de tablas en la base de datos.
ollamh
1
agregue "select * from (" al comienzo y ") como orden de salida por exacto_cuenta_cuenta desc" al final de la consulta generada después de eliminar la última UNION para obtener orden por recuento de tabla desc
Raghavendra
Para excluir vistas: WHERE table_schema = ' my_schema ' y TABLE_TYPE LIKE '% TABLE%'
Watson el
38

Acabo de correr:

show table status;

Esto le dará el recuento de filas para CADA tabla más un montón de otra información. Solía ​​usar la respuesta seleccionada arriba, pero esto es mucho más fácil.

No estoy seguro de si esto funciona con todas las versiones, pero estoy usando 5.5 con el motor InnoDB.

djburdick
fuente
55
Desafortunadamente, si está usando InnoDB, este enfoque adolece de las mismas imprecisiones que los otros métodos descritos anteriormente. Por ejemplo, tengo una tabla InnoDB que tiene aproximadamente 65,000 filas, pero estos métodos aquí informan que tiene entre 350,000 y más de 780,000.
PeterToTheThird
Para una base de datos con pocas filas, es bastante precisa (o lo suficientemente precisa para mis necesidades). Me dio 1086 filas para una tabla que COUNT (*) informó 904 filas.
Magne
Con mucho, la mejor respuesta. Uso InnoDB pero solo necesito un comando rápido para conocer el orden de magnitud.
Nemo
En serio, desearía que esto fuera aceptado. No uso InnoDB y me da una respuesta exacta.
Kolob Canyon
1
El número de filas no es exacto, pero "Aumento automático" puede proporcionarle un número exacto si no eliminó ninguna fila de dichas tablas.
Peter T.
13
 SELECT TABLE_NAME,SUM(TABLE_ROWS) 
 FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_SCHEMA = 'your_db' 
 GROUP BY TABLE_NAME;

Eso es todo lo que necesitas.

Gustavo Castro
fuente
1
produce filas de tabla estimadas - compárelo con "mysql_num_rows ($ tableresult)"
Kreeverp
1
esa es la mejor respuesta en realidad! También el más simple para ser ejecutado desde mysql cli:mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
loretoparisi
11

Este procedimiento almacenado enumera tablas, cuenta registros y produce un número total de registros al final.

Para ejecutarlo después de agregar este procedimiento:

CALL `COUNT_ALL_RECORDS_BY_TABLE` ();

-

El procedimiento:

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
Jake Drew
fuente
8

Manera simple:

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

Ejemplo de resultado:

+----------------+-----------------+
| 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 |
+----------------+-----------------+
Eduardo Cuomo
fuente
4

Hay un pequeño truco / solución para este problema de estimación.

Auto_Increment: por alguna razón, esto devuelve un recuento de filas mucho más preciso para su base de datos si tiene un incremento automático configurado en las tablas.

Encontré esto al explorar por qué la información de la tabla no coincidía con los datos reales.

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)

Luego, podría usar PHP o lo que sea para devolver el máximo de las 2 columnas de datos para obtener la "mejor estimación" para el recuento de filas.

es decir

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;

El incremento automático siempre será +1 * (recuento de tablas) en filas, pero incluso con 4,000 tablas y 3 millones de filas, eso es 99.9% de precisión. Mucho mejor que las filas estimadas.

La belleza de esto es que los recuentos de filas devueltos en performance_schema también se borran para usted, porque el mayor no funciona en nulos. Sin embargo, esto puede ser un problema si no tiene tablas con incremento automático.

usuario3260912
fuente
3

Puedes probar esto. Está funcionando bien para mí.

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;
Nimesh07
fuente
2

Si usa la base de datos information_schema, puede usar este código mysql (la parte where hace que la consulta no muestre tablas que tienen un valor nulo para las filas):

SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
Robin Manoli
fuente
1

La siguiente consulta produce una consulta (otra) que obtendrá el valor de count (*) para cada tabla, de cada esquema, enumerado en information_schema.tables. El resultado completo de la consulta que se muestra aquí, todas las filas juntas, comprenden una instrucción SQL válida que termina en punto y coma, sin 'unión' colgante. La unión colgante se evita mediante el uso de una unión en la consulta a continuación.

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);';
usuario1575139
fuente
1

Esto es lo que hago para obtener el recuento real (sin usar el esquema)

Es más lento pero más preciso.

Es un proceso de dos pasos en

  1. Obtenga una lista de tablas para su base de datos. Puedes conseguirlo usando

    mysql -uroot -p mydb -e "show tables"
  2. Cree y asigne la lista de tablas a la variable de matriz en este script bash (separadas por un solo espacio, como en el código a continuación)

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

    chmod +x script.sh; ./script.sh
lsaffie
fuente
1

Una opción más: para no InnoDB, utiliza datos de information_schema.TABLES (ya que es más rápido), para InnoDB: seleccione count (*) para obtener el conteo exacto. También ignora las vistas.

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;

Si su base de datos tiene muchas tablas grandes de InnoDB, contar todas las filas puede llevar más tiempo.

filimonov
fuente
0

Así es como cuento TABLAS y TODOS LOS REGISTROS 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.";
koswara1482
fuente
¿Por qué no utiliza count (*) si ignorará los datos?
Svetoslav Marinov
0

Poster quería contar las filas sin contar, pero no especificaba qué motor de tabla. Con InnoDB, solo conozco una forma, que es contar.

Así es como recojo mis papas:

# 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"
}

No estoy haciendo ninguna afirmación sobre esto aparte de que esta es una forma realmente fea pero efectiva de obtener cuántas filas existen en cada tabla en la base de datos, independientemente del motor de la tabla y sin tener que tener permiso para instalar procedimientos almacenados, y sin necesidad de instalar rubí o php. Sí, está oxidado. Si cuenta. cuenta (*) es precisa.

apotek
fuente
0

Basado en la respuesta de @ Nathan anterior, pero sin necesidad de "eliminar la unión final" y con la opción de ordenar la salida, utilizo el siguiente SQL. Genera otra instrucción SQL que luego se ejecuta:

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 

Usted necesita un valor suficientemente grande de group_concat_max_lenla variable del servidor, pero desde MariaDb 10.2.4 debe tener un valor predeterminado de 1M.

Adán
fuente
0

El siguiente código genera la consulta de selección para todos los cuentos. Simplemente elimine el último "UNION ALL", seleccione todos los resultados y pegue una nueva ventana de consulta para ejecutar.

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'
vasto
fuente
-1

Si desea los números exactos, use el siguiente script de ruby. Necesitas Ruby y RubyGems.

Instala las siguientes gemas:

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

Archivo: 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

Regrese a la línea de comando:

$> ruby count_table_records.rb

Salida:

Table users has 7328974 rows.
Michael Voigt
fuente
-4

Si conoce el número de tablas y sus nombres, y suponiendo que cada una tenga claves principales, puede usar una combinación cruzada en combinación con COUNT(distinct [column])para obtener las filas que provienen de cada tabla:

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

Aquí hay un ejemplo de SQL Fiddle .

AdamMc331
fuente