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


347

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


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

1
SELECT count (table_name) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'YOUR_DB' даст количество таблиц в вашей базе данных
шаси кант

Ответы:


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

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


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

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

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

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

2
ВЫБЕРИТЕ TABLE_NAME, SUM (TABLE_ROWS) N ИЗ INFORMATION_SCHEMA.TABLES, ГДЕ TABLE_SCHEMA = '{your_db}' группа по TABLE_NAME;
PiyusG

177

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

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

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

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

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

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

Упс ... хотелось бы, чтобы я видел слово "Оценено" раньше, чем ... как вчера! Разве ответ не должен быть отклонен? Поскольку ОП не просил «оценивать» и кажется глупым думать, что он может захотеть оценить. "Смета" Могут ли такие, как я, боролись от пропуска "сметы"?
Kreeverp

111

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

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

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

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

Чтобы исключить просмотры: WHERE table_schema = ' my_schema ' и TABLE_TYPE LIKE '% TABLE%'
Уотсон,

39

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

show table status;

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

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


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

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

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

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

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

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

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


1
производит приблизительные строки таблицы - сравните с «mysql_num_rows ($ tableresult)»
Kreeverp

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

11

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

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

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

8

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

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

4

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

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


3

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

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

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

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

1

Следующий запрос создает (другой) запрос, который будет получать значение 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);';

1

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

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

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

  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

1

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

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


0

Вот как я считаю ТАБЛИЦЫ и ВСЕ ЗАПИСИ, используя 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 (*), если вы будете игнорировать данные?
Святослав Маринов

0

Постер хотел подсчитать количество строк без учета, но не указал, какой движок таблицы. С 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. Да, это ржаво. Да, это имеет значение. количество (*) является точным.


0

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


0

Код ниже генерирует запрос выбора для всех сказок. Просто удалите последний "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'

-1

Если вы хотите точные цифры, используйте следующий скрипт 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.

-4

Если вы знаете количество таблиц и их имена и предполагаете, что у каждой из них есть первичные ключи, вы можете использовать перекрестное объединение в сочетании с, 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 .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.