Чи є спосіб отримати кількість рядків у всіх таблицях бази даних MySQL, не запускаючи а SELECT count()
на кожній таблиці?
Чи є спосіб отримати кількість рядків у всіх таблицях бази даних MySQL, не запускаючи а SELECT count()
на кожній таблиці?
Відповіді:
SELECT SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{your_db}';
Зверніть увагу на документи: Однак для таблиць InnoDB кількість рядків - це лише приблизна оцінка, яка використовується в оптимізації SQL. Вам потрібно буде використовувати COUNT (*) для точного підрахунку (що дорожче).
Можливо, ви можете скласти щось разом із таблицею таблиць . Я ніколи цього не робив, але, схоже, він містить стовпчик для TABLE_ROWS та один для імені TABLE .
Щоб отримати рядки за таблицею, ви можете використовувати такий запит:
SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';
Як і @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)
Я просто біжу:
show table status;
Це дасть вам кількість рядків для КОЖНОГО столу плюс купу іншої інформації. Раніше я використовував обрану відповідь, але це набагато простіше.
Я не впевнений, чи працює це у всіх версіях, але я використовую 5.5 з двигуном InnoDB.
SELECT TABLE_NAME,SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'your_db'
GROUP BY TABLE_NAME;
Це все, що вам потрібно.
mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
Ця збережена процедура перераховує таблиці, підраховує записи та створює загальну кількість записів на кінець.
Щоб запустити його після додавання цієї процедури:
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
Простий спосіб:
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 |
+----------------+-----------------+
Існує трохи злому / вирішення цієї проблеми з оцінкою.
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, також стираються для вас, тому що найбільший не працює на нулях. Це може бути проблемою, якщо у вас немає таблиць з автоматичним збільшенням.
Якщо ви використовуєте базу даних information_schema, ви можете використовувати цей код mysql (частина де запит не показує таблиці, що мають нульове значення для рядків):
SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
Наступний запит створює (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);';
Це те, що я роблю, щоб отримати фактичну кількість (не використовуючи схему)
Це повільніше, але точніше.
Це процес у два етапи
Отримайте список таблиць для вашого db. Ви можете отримати це за допомогою
mysql -uroot -p mydb -e "show tables"
Створіть і призначте список таблиць змінній масиву в цьому скрипті bash (розділеному одним пробілом, як у коді нижче)
array=( table1 table2 table3 )
for i in "${array[@]}"
do
echo $i
mysql -uroot mydb -e "select count(*) from $i"
done
Виконати:
chmod +x script.sh; ./script.sh
Ще один варіант: для не 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, підрахунок усіх рядків може зайняти більше часу.
Ось так я рахую ТАБЛИЦІ І ВСІ ЗАПИСИ за допомогою 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.";
Плакат хотів рахувати рядки без підрахунку, але не вказав двигун таблиці. Що стосується 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 (*) точний.
На підставі відповіді @ 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М.
Код нижче генерації запиту вибору для всіх казок. Просто видаліть останній "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'
Якщо ви хочете точні цифри, використовуйте наступний сценарій рубіну. Вам потрібні 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.
Якщо ви знаєте кількість таблиць та їх назви, і якщо припустити, що в кожній з них є первинні ключі, ви можете використовувати перехресне з'єднання в поєднанні з, 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 .