Есть ли способ получить количество строк во всех таблицах в базе данных 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 NAME .
Чтобы получить строки на таблицу, вы можете использовать запрос, подобный этому:
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 или любой другой метод, чтобы вернуть максимум из двух столбцов данных, чтобы получить «наилучшую оценку» для количества строк.
т.е.
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 не работает с нулями. Это может быть проблемой, если у вас нет таблиц с автоматическим приращением.
Вы можете попробовать это. Это работает нормально для меня.
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;
Если вы используете базу данных information_schema, вы можете использовать этот код mysql (часть where заставляет запрос не показывать таблицы с нулевым значением для строк):
SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
Следующий запрос создает (другой) запрос, который будет получать значение 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);';
Это то, что я делаю, чтобы получить фактический счетчик (без использования схемы)
Это медленнее, но точнее.
Это двухэтапный процесс в
Получить список таблиц для вашей базы данных. Вы можете получить это используя
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 - выберите количество (*), чтобы получить точное количество. Также он игнорирует взгляды.
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. Да, это ржаво. Да, это имеет значение. количество (*) является точным.
Основываясь на ответе @ Натана выше, но без необходимости «удалять окончательное объединение» и с возможностью сортировки вывода, я использую следующий 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'
Если вы хотите точные цифры, используйте следующий скрипт 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.
Если вы знаете количество таблиц и их имена и предполагаете, что у каждой из них есть первичные ключи, вы можете использовать перекрестное объединение в сочетании с, 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 .