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