Отримайте підрахунок записів для всіх таблиць у базі даних 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' дасть кількість таблиць у вашій базі даних
— shasi kanth

Відповіді:


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

Зверніть увагу на документи: Однак для таблиць InnoDB кількість рядків - це лише приблизна оцінка, яка використовується в оптимізації SQL. Вам потрібно буде використовувати COUNT (*) для точного підрахунку (що дорожче).


267
або, якщо потрібно для кожної таблиці: SELECT ім'я таблиці, 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 (*) ОТ t, що, однак, набагато повільніше
— Маркування

2
Джайцу, ні, це не так. count (*) (або більш реально count (id)) - це те, що використовує mysql для підрахунку його рядків, чи не так? У будь-якому випадку, я просто перевірив це і отримав більшу кількість для дзвінка count (), що б того не було.
— кодигман

2
ВИБІРТЕ TABLE_NAME, SUM (TABLE_ROWS) N ВІД ІНФОРМАЦІЇ_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}' групи від TABLE_NAME;
— PiyusG

176

Можливо, ви можете скласти щось разом із таблицею таблиць . Я ніколи цього не робив, але, схоже, він містить стовпчик для TABLE_ROWS та один для імені TABLE .

Щоб отримати рядки за таблицею, ви можете використовувати такий запит:

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

4
Чи є інший спосіб отримати table_row та table_name? Тому що я хочу точний результат, а не приблизна оцінка. Дякую.
— крунал шах

1
як згаданий kuranl, це повертає лише оцінку і, ймовірно, поверне різні результати, коли пробіжить пару разів
— Kris

Таблиці, що містять щонайменше ~ 250 записів, схоже, повідомляють про різну кількість рядків щоразу, коли я запускаю цей запит.
— Артур

На жаль, хотілося б, щоб я бачив слово "Оцінений" перед рукою ... як учора! Чи не слід відхиляти відповідь? Оскільки ОП не просив "оцінювати", і здається дурним думати, що він може хотіти оцінки. "Оцінка" Чи могли б врятувати маронів, як я, від пропуску "оцінки"?
— Кріверп

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
Дякую, я сподівався, що мені не доведеться встановлювати плагіни / дорогоцінні камені, щоб отримати точні підрахунки.
— bradvido

Виконується занадто багато часу для виконання у випадку великої кількості таблиць у базі даних.
— оллам

1
додайте "select * from (" на початку та ") як вихідний порядок точно_row_count desc" в кінці згенерованого запиту після видалення останнього UNION, щоб отримати замовлення за кількістю таблиць desc
— Raghavendra

Щоб виключити представлення даних: 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 або будь-що інше, щоб повернути максимум 2 стовпців даних, щоб дати "найкращу оцінку" для кількості рядків.

тобто

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


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 (частина де запит не показує таблиці, що мають нульове значення для рядків):

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

1

Наступний запит створює (nother) запит, який отримає значення 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. Отримайте список таблиць для вашого db. Ви можете отримати це за допомогою

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


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. Так, його іржаве. Так, це рахується. count (*) точний.


0

На підставі відповіді @ 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 він повинен за замовчуванням до 1М.


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 і 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.