431 votes

Obtenir le nombre d'enregistrements pour toutes les tables dans la base de données MySQL

Y a-t-il un moyen d'obtenir le nombre de lignes dans toutes les tables d'une base de données MySQL sans exécuter un SELECT count() sur chaque table ?

3 votes

Réponse étendue qui est également précise pour InnoDB : stackoverflow.com/questions/24707814/…

2 votes

SÉLECTIONNEZ count(table_name) DEPUIS INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'YOUR_DB' donnera le nombre de tables dans votre base de données.

495voto

Hates_ Points 8657
SÉLECTIONNEZ SUM(TABLE_ROWS) 
     DEPUIS INFORMATION_SCHEMA.TABLES 
     WHERE TABLE_SCHEMA = '{your_db}';

Note dans les docs cependant: Pour les tables InnoDB, le nombre de lignes n'est qu'une estimation approximative utilisée dans l'optimisation SQL. Vous devrez utiliser COUNT(*) pour des comptages exacts (ce qui est plus coûteux).

313 votes

Ou, si vous voulez pour chaque tableau: SELECT table_name, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}';

8 votes

Y a-t-il un autre moyen d'obtenir table_row et table_name ? Parce que je veux un résultat exact, pas une approximation grossière. Merci.

3 votes

@krunalshah, C'est l'une des restrictions d'InnoDB. Voir dev.mysql.com/doc/refman/5.0/fr/innodb-restrictions.html, section Restrictions on InnoDB Tables, pour plus d'informations. Vous pourriez toujours utiliser un SELECT COUNT(*) FROM t, ce qui est cependant beaucoup plus lent

226voto

gpojd Points 12043

Vous pouvez probablement assembler quelque chose avec Tables table. Je ne l'ai jamais fait, mais il semble avoir une colonne pour TABLE_ROWS et une pour NOM DE TABLE.

Pour obtenir les lignes par table, vous pouvez utiliser une requête comme ceci:

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

7 votes

Y a-t-il un autre moyen d'obtenir table_row et table_name ? Parce que je veux un résultat exact et non une estimation approximative. Merci.

2 votes

Comme kuranl l'a mentionné, cela ne renvoie qu'une estimation et donnera probablement des résultats différents lorsqu'il sera exécuté plusieurs fois

1 votes

Les tableaux avec au moins ~250 enregistrements semblent signaler un nombre différent de lignes à chaque fois que j'exécute cette requête.

162voto

Nathan Points 1975

Comme @Venkatramanan et d'autres, j'ai trouvé que INFORMATION_SCHEMA.TABLES était peu fiable (en utilisant InnoDB, MySQL 5.1.44), donnant des comptages de lignes différents à chaque fois que je l'exécute même sur des tables en attente. Voici une manière relativement bidouille (mais flexible/adaptable) de générer une grande déclaration SQL que vous pouvez coller dans une nouvelle requête, sans installer de gemmes Ruby et autres.

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 = '**mon_schema**';

Cela produit une sortie comme ceci:

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 

Copiez et collez sauf pour le dernier UNION pour obtenir une belle sortie comme,

+------------------+-----------------+
| 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)

3 votes

Merci, j'espérais ne pas avoir à installer de plugins/gems pour obtenir des comptes exacts.

1 votes

Prend trop de temps à s'exécuter en cas de grand nombre de tables dans la base de données.

1 votes

Ajoutez "select * from (" au début et ") as output order by exact_row_count desc" à la fin de la requête générée après avoir supprimé le dernier UNION pour obtenir l'ordre par décompte de table desc

59voto

djburdick Points 2254

Je viens juste de lancer :

show table status;

Cela vous donnera le nombre de lignes pour CHAQUE table ainsi qu'une multitude d'autres informations. Je l'habitude d'utiliser la réponse sélectionnée ci-dessus, mais c'est beaucoup plus facile.

Je ne suis pas sûr si cela fonctionne avec toutes les versions, mais j'utilise la version 5.5 avec le moteur InnoDB.

10 votes

Malheureusement, si vous utilisez InnoDB, cette approche souffre des mêmes inexactitudes que les autres méthodes décrites ci-dessus. Par exemple, j'ai une table InnoDB qui compte environ 65 000 lignes, pourtant ces méthodes ici rapportent qu'elle en compte de 350 000 à plus de 780 000.

0 votes

Pour une base de données avec peu de lignes, c'est assez précis (ou, assez précis pour mes besoins). Il m'a donné 1086 lignes pour une table que COUNT(*) a rapporté 904 lignes.

0 votes

De loin la meilleure réponse. J'utilise InnoDB mais j'ai seulement besoin d'une commande rapide pour connaître l'ordre de grandeur.

13voto

Jake Drew Points 49

Ce procédé stocké répertorie les tables, compte les enregistrements et produit un nombre total d'enregistrements à la fin.

Pour l'exécuter après avoir ajouté cette procédure :

CALL `COUNT_ALL_RECORDS_BY_TABLE` ();

-

La Procédure :

DELIMITER $$

CREATE DEFINER=`root`@`127.0.0.1` PROCÉDURE `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

0 votes

C'est ce que je cherchais, sympa. Comment puis-je ajouter une clause Where dans la requête de la table utilisateur, je veux dire là où vous comptez les lignes dans les tables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X