Получить количество записей для всех таблиц в базе данных MySQL - PullRequest
298 голосов
/ 13 ноября 2008

Есть ли способ получить количество строк во всех таблицах в базе данных MySQL без запуска SELECT count() для каждой таблицы?

Ответы [ 16 ]

365 голосов
/ 13 ноября 2008
SELECT SUM(TABLE_ROWS) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE TABLE_SCHEMA = '{your_db}';

Примечание из документации: Для таблиц InnoDB количество строк - это только приблизительная оценка , используемая в оптимизации SQL. Вам нужно будет использовать COUNT (*) для точного подсчета (что дороже).

155 голосов
/ 13 ноября 2008

Вы, вероятно, можете что-то сложить вместе с Таблица таблиц . Я никогда не делал этого, но, похоже, у него есть столбец для TABLE_ROWS и один для TABLE NAME .

Чтобы получить количество строк в таблице, вы можете использовать такой запрос:

SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';
96 голосов
/ 01 января 2012

Как и @Venkatramanan и другие, я обнаружил, что INFORMATION_SCHEMA.TABLES ненадежен (с использованием InnoDB, MySQL 5.1.44), предоставляя различное количество строк каждый раз, когда я запускаю его, даже на успокоенных таблицах. Вот довольно хакерский (но гибкий / адаптируемый) способ генерирования большого оператора SQL, который вы можете вставить в новый запрос, без установки гемов 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**';

Это производит вывод как это:

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 

Скопируйте и вставьте, кроме последнего UNION, чтобы получить хороший вывод, например,

+------------------+-----------------+
| 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)
31 голосов
/ 24 июля 2013

Я просто бегу:

show table status;

Это даст вам количество строк для КАЖДОЙ таблицы плюс кучу другой информации. Я использовал выбранный ответ выше, но это намного проще.

Я не уверен, что это работает со всеми версиями, но я использую 5.5 с движком InnoDB.

10 голосов
/ 02 августа 2012
 SELECT TABLE_NAME,SUM(TABLE_ROWS) 
 FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_SCHEMA = 'your_db' 
 GROUP BY TABLE_NAME;

Это все, что тебе нужно.

10 голосов
/ 29 марта 2011

Эта хранимая процедура выводит список таблиц, подсчитывает записи и создает общее количество записей в конце.

Чтобы запустить его после добавления этой процедуры:

CALL `COUNT_ALL_RECORDS_BY_TABLE` ();

-

Процедура:

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
3 голосов
/ 15 февраля 2014

Вы можете попробовать это. У меня это нормально работает.

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 голосов
/ 25 ноября 2016

Есть немного хака / обходного пути к этой проблеме оценки.

Auto_Increment - по некоторым причинам это возвращает намного более точное количество строк для вашей базы данных, если у вас настроено автоматическое приращение для таблиц.

Обнаружено это при изучении того, почему информация в отображаемой таблице не совпадает с фактическими данными.

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)

Затем можно легко использовать PHP или любой другой метод, чтобы вернуть максимум из двух столбцов данных, чтобы получить «наилучшую оценку» для количества строк.

т.е.

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;

Автоинкремент всегда будет отключен на +1 * (количество таблиц), но даже с 4000 таблицами и 3 миллионами строк это точность составляет 99,9%. Гораздо лучше, чем предполагаемые строки.

Прелесть этого в том, что счетчики строк, возвращаемые в performance_schema, также стираются для вас, поскольку самая большая не работает с нулями. Это может быть проблемой, если у вас нет таблиц с автоинкрементом.

2 голосов
/ 10 ноября 2011

Если вы используете базу данных information_schema, вы можете использовать этот код mysql (часть where заставляет запрос не показывать таблицы с нулевым значением для строк):

SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
1 голос
/ 07 ноября 2016

Еще один вариант: для не InnoDB он использует данные из information_schema.TABLES (как это быстрее), для InnoDB - выберите count (*), чтобы получить точный счет. Также игнорирует просмотры.

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;

Если в вашей базе данных много больших таблиц InnoDB, подсчет всех строк может занять больше времени.

...