Получить количество записей для всех таблиц в базе данных MySQL

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

Расширенный ответ, который также подходит для InnoDB: stackoverflow.com/questions/24707814/…

gwideman 12.07.2014 03:53
ВЫБЕРИТЕ количество (имя_таблицы) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'YOUR_DB' даст количество таблиц в вашей базе данных
shasi kanth 22.05.2018 15:00
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
371
2
344 283
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

С Таблицы стол, наверное, можно что-нибудь скомпоновать. Я никогда этого не делал, но похоже, что в нем есть столбец для TABLE_ROWS и один для НАЗВАНИЕ ТАБЛИЦЫ.

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

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

Есть ли другой способ получить table_row и table_name? Потому что мне нужен точный результат, а не приблизительная оценка. Спасибо.

krunal shah 01.04.2011 07:35

как упоминал Куранл, это возвращает только оценку и, вероятно, вернет разные результаты при запуске несколько раз

Kris 12.12.2012 16:12

Таблицы с как минимум ~ 250 записями, кажется, сообщают о разном количестве строк каждый раз, когда я запускаю этот запрос.

Arthur 01.08.2013 18:25

Ой ... Хотел бы я видеть слово "Оценка" перед рукой ... как вчера! Не следует ли отказываться от ответа? Поскольку ОП не просил «оценку», и кажется глупым думать, что ему может понадобиться оценка. "оценка" Могла бы спасти маронов вроде меня от пропуска "оценки"?

user4386053 30.12.2015 08:06
Ответ принят как подходящий
SELECT SUM(TABLE_ROWS) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE TABLE_SCHEMA = '{your_db}';

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

или, если вы хотите для каждой таблицы: SELECT table_name, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}';

TheSoftwareJedi 13.11.2008 05:03

Есть ли другой способ получить table_row и table_name? Потому что мне нужен точный результат, а не приблизительная оценка. Спасибо.

krunal shah 01.04.2011 07:35

@krunalshah, это одно из ограничений InnoDB. См. dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html, раздел Ограничения для таблиц InnoDB, для получения дополнительной информации. Вы всегда можете использовать SELECT COUNT (*) FROM t, что, однако, намного медленнее

Marking 23.02.2012 15:21

@Marking Я почти уверен, что SELECT COUNT(*) ... все еще подлежит подсчету

JamesHalsall 15.03.2013 16:52

Джайцу, нет, это не так. count (*) (или более реалистично count (id)) - это то, что mysql использует для подсчета строк, не так ли? В любом случае, я просто протестировал его и получил большее число для вызова count (), чего бы оно ни стоило.

codygman 24.05.2013 20:24

SELECT TABLE_NAME, SUM (TABLE_ROWS) N FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}' group by TABLE_NAME;

PiyusG 17.11.2014 09:48

Где именно "COUNT (*)" соответствует приведенному выше ответу? Хотелось бы точного результата.

user4386053 14.03.2015 22:02

Почему в моем случае TABLE_ROWS несовместима для каждого запроса? Я использую mariadb 10

Fandi Susanto 07.10.2016 12:15

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

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

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

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

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

Если вам нужны точные числа, используйте следующий скрипт ruby. Вам нужны Ruby и RubyGems.

Установите следующие драгоценные камни:

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

Файл: 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

Вернитесь в командную строку:

$> ruby count_table_records.rb

Выход:

Table users has 7328974 rows.

Как и @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)

Спасибо, я надеялся, что мне не придется устанавливать какие-либо плагины / драгоценные камни, чтобы получить точные подсчеты.

bradvido 03.09.2014 00:02

Слишком долго выполняется в случае большого количества таблиц в базе данных.

ollamh 15.05.2018 10:13

добавить "select * from (" в начале и ") в качестве порядка вывода по точному_строку_count desc" в конце сгенерированного запроса после удаления последнего UNION, чтобы получить порядок по количеству таблиц по убыванию

Raghavendra 22.06.2018 08:42

Чтобы исключить представления: WHERE table_schema = 'my_schema' и TABLE_TYPE LIKE '% TABLE%'

Watson 27.07.2019 03:42

Это НАСТОЯЩИЙ ответ для меня.

Abhijeet Nagre 18.07.2020 16:48

Вот как я считаю ТАБЛИЦЫ и ВСЕ ЗАПИСИ с помощью 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.";

Почему бы вам не использовать count (*), если вы будете игнорировать данные?

Svetoslav Marinov 18.05.2020 11:49
 SELECT TABLE_NAME,SUM(TABLE_ROWS) 
 FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_SCHEMA = 'your_db' 
 GROUP BY TABLE_NAME;

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

производит оценочные строки таблицы - сравните с "mysql_num_rows ($ tableresult)"

user4386053 30.12.2015 08:02

это лучший ответ на самом деле! Также проще выполнить из mysql cli: mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;

loretoparisi 20.03.2018 12:33

Следующий запрос создает (другой) запрос, который получит значение count (*) для каждой таблицы из каждой схемы, перечисленной в information_schema.tables. Весь результат запроса, показанный здесь - все строки вместе взятые - представляет собой действительный оператор SQL, оканчивающийся точкой с запятой - без «зависшего» «объединения». Висящего объединения можно избежать, используя объединение в запросе ниже.

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);';

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

show table status;

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

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

К сожалению, если вы используете InnoDB, этот подход страдает теми же неточностями, что и другие методы, описанные выше. Например, у меня есть таблица InnoDB, содержащая примерно 65 000 строк, но эти методы сообщают, что в ней содержится от 350 000 до более 780 000 строк.

PeterToTheThird 12.03.2014 05:53

Для БД с несколькими строками это довольно точно (или, достаточно точно для моих нужд). Он дал мне 1086 строк для таблицы, в которой COUNT (*) сообщил о 904 строках.

Magne 10.12.2014 11:58

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

Nemo 11.01.2016 00:03

Серьезно, хотелось бы, чтобы это было принято. Не использую InnoDB и дает мне точный ответ.

Kolob Canyon 25.02.2016 07:37

Это берет столбец TABLE_ROWS из таблицы INFORMATION_SCHEMA.TABLES. Обратите внимание, что эта информация (предоставленная show table status или столбцом TABLE_ROWS) является лишь приблизительной оценкой, которая может быть неточной для InnoDB (я еще не тестировал MyISAM).

Eugen Mihailescu 08.05.2016 21:50

Количество строк не является точным, но «Auto_increment» может дать вам точное количество, если вы не удалили ни одной строки из таких таблиц.

Peter T. 22.08.2016 14:01

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

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;

Это то, что я делаю, чтобы получить фактическое количество (без использования схемы)

Это медленнее, но точнее.

Это двухэтапный процесс на

  1. Получите список таблиц для вашей БД. Вы можете получить это, используя

    mysql -uroot -p mydb -e "show tables"
    
  2. Создайте и назначьте список таблиц переменной массива в этом сценарии bash (разделенных одним пробелом, как в приведенном ниже коде)

    array=( table1 table2 table3 )
    
    for i in "${array[@]}"
    do
        echo $i
        mysql -uroot mydb -e "select count(*) from $i"
    done
    
  3. Запустить его:

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

Плакат требовал подсчета строк без подсчета, но не указывал, какой движок таблицы. С InnoDB я знаю только один способ - считать.

Вот как я собираю картошку:

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

Я не делаю никаких утверждений по этому поводу, кроме того, что это действительно уродливый, но эффективный способ узнать, сколько строк существует в каждой таблице в базе данных, независимо от механизма таблицы и без необходимости иметь разрешение на установку хранимых процедур и без необходимости устанавливать рубин или php. Да, ржавый. Да, это важно. count (*) является точным.

Если вы знаете количество таблиц и их имена и предполагаете, что каждая из них имеет первичные ключи, вы можете использовать перекрестное соединение в сочетании с COUNT(distinct [column]), чтобы получить строки из каждой таблицы:

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

Вот пример SQL Fiddle.

Еще один вариант: для не 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, подсчет всех строк может занять больше времени.

Я добавил строку с SELECT CONCAT(@selects, ' ORDER BY TABLE_ROWS ') INTO @selects; перед PREPARE, чтобы получить более читаемый результат, но это лучший ответ для меня.

Balmipour 14.07.2020 01:32

Есть небольшое решение этой проблемы с оценкой.

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, также стираются для вас, потому что величайший не работает с нулевыми значениями. Однако это может быть проблемой, если у вас нет таблиц с автоматическим приращением.

Простой способ:

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

Пример результата:

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

Основываясь на ответе @Nathan выше, но без необходимости «удалять окончательное объединение» и с возможностью сортировки вывода, я использую следующий SQL. Он генерирует еще один оператор SQL, который затем просто запускается:

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 

Вам действительно нужно достаточно большое значение переменной сервера group_concat_max_len, но в MariaDb 10.2.4 оно должно по умолчанию равняться 1M.

Приведенный ниже код генерирует запрос выбора для всех сказок. Просто удалите последний "UNION ALL", выберите все результаты и вставьте новое окно запроса для запуска.

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'

Другие вопросы по теме