มีวิธีรับจำนวนแถวในตารางทั้งหมดในฐานข้อมูล MySQL โดยไม่ต้องรัน a SELECT count()
ในแต่ละตารางหรือไม่?
มีวิธีรับจำนวนแถวในตารางทั้งหมดในฐานข้อมูล MySQL โดยไม่ต้องรัน a SELECT count()
ในแต่ละตารางหรือไม่?
คำตอบ:
SELECT SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{your_db}';
หมายเหตุจากเอกสาร:สำหรับตาราง InnoDB การนับแถวเป็นเพียงการประมาณการคร่าวๆที่ใช้ในการปรับ SQL ให้เหมาะสม คุณจะต้องใช้ COUNT (*) สำหรับจำนวนที่แน่นอน (ซึ่งแพงกว่า)
คุณอาจจะสามารถนำสิ่งที่ร่วมกันกับตารางตาราง ฉันไม่เคยทำ แต่มันดูเหมือนว่ามันมีคอลัมน์สำหรับTABLE_ROWSและหนึ่งสำหรับชื่อตาราง
ในการรับแถวต่อตารางคุณสามารถใช้แบบสอบถามเช่นนี้:
SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';
เช่น @Venkatramanan และคนอื่น ๆ ฉันพบว่า Information_SCHEMA.TABLES ไม่น่าเชื่อถือ (ใช้ InnoDB, MySQL 5.1.44) ให้นับจำนวนแถวที่แตกต่างกันทุกครั้งที่ฉันเรียกใช้แม้ในตารางที่ระงับ นี่เป็นวิธีที่ค่อนข้างแฮ็ก (แต่ยืดหยุ่น / ปรับเปลี่ยนได้) วิธีสร้างคำสั่ง SQL ขนาดใหญ่ที่คุณสามารถวางลงในคิวรีใหม่ได้โดยไม่ต้องติดตั้งอัญมณีและสิ่งของของทับทิม
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 * (นับตาราง) เสมอ แต่ถึงแม้จะมี 4,000 ตารางและ 3 ล้านแถวที่ถูกต้อง 99.9% ดีกว่าแถวที่ประมาณไว้มาก
ความสวยงามของสิ่งนี้คือการที่แถวที่ส่งคืนมาใน performance_schema นั้นถูกลบทิ้งสำหรับคุณเช่นกันเพราะยิ่งใหญ่ที่สุดไม่สามารถใช้งานได้กับค่า Null นี่อาจเป็นปัญหาหากคุณไม่มีตารางที่มีการเพิ่มอัตโนมัติ
คุณสามารถลองสิ่งนี้ มันทำงานได้ดีสำหรับฉัน
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;
หากคุณใช้ data_schema ฐานข้อมูลคุณสามารถใช้รหัส mysql นี้ได้ (ส่วนที่ทำให้แบบสอบถามไม่แสดงตารางที่มีค่า Null สำหรับแถว):
SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
แบบสอบถามต่อไปนี้สร้างแบบสอบถาม (nother) ที่จะได้รับค่านับ (*) สำหรับทุกตารางจากทุกสคีมาแสดงใน 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"
สร้างและกำหนดรายการตารางให้กับตัวแปรอาร์เรย์ในสคริปต์ทุบตีนี้ (คั่นด้วยช่องว่างเดียวเหมือนในรหัสด้านล่าง)
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 จะใช้ข้อมูลจาก data_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 ขนาดใหญ่จำนวนมากการนับแถวทั้งหมดอาจใช้เวลามากขึ้น
นี่คือวิธีที่ฉันนับ TABLES และ RECORDS ทั้งหมดโดยใช้ 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 ค่าเริ่มต้นควรเป็น 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 และ 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;
นี่คือตัวอย่างของซอ Fiddle