Có cách nào để lấy số lượng hàng trong tất cả các bảng trong cơ sở dữ liệu MySQL mà không cần chạy SELECT count()
trên mỗi bảng không?
Có cách nào để lấy số lượng hàng trong tất cả các bảng trong cơ sở dữ liệu MySQL mà không cần chạy SELECT count()
trên mỗi bảng không?
Câu trả lời:
SELECT SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{your_db}';
Lưu ý từ các tài liệu mặc dù: Đối với các bảng InnoDB, số lượng hàng chỉ là ước tính sơ bộ được sử dụng trong tối ưu hóa SQL. Bạn sẽ cần sử dụng COUNT (*) để tính chính xác (đắt hơn).
Bạn có thể có thể đặt một cái gì đó cùng với bảng Bảng . Tôi chưa bao giờ thực hiện nó, nhưng có vẻ như nó có một cột cho TABLE_lawS và một cột cho TABLE NAME .
Để nhận hàng trên mỗi bảng, bạn có thể sử dụng truy vấn như sau:
SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';
Giống như @Venkatramanan và những người khác, tôi thấy Information_SCHema.TABLES không đáng tin cậy (sử dụng InnoDB, MySQL 5.1.44), đưa ra số lượng hàng khác nhau mỗi khi tôi chạy nó ngay cả trên các bảng được cách ly. Đây là một cách tương đối khó (nhưng linh hoạt / có thể thích ứng) để tạo một câu lệnh SQL lớn mà bạn có thể dán vào một truy vấn mới, mà không cần cài đặt các công cụ và đá quý của 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**';
Nó tạo ra đầu ra như thế này:
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
Sao chép và dán ngoại trừ UNION cuối cùng để có đầu ra đẹp như,
+------------------+-----------------+
| 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)
Tôi chỉ chạy
show table status;
Điều này sẽ cung cấp cho bạn số lượng hàng cho MỌI bảng cộng với một loạt các thông tin khác. Tôi đã từng sử dụng câu trả lời được chọn ở trên, nhưng điều này dễ dàng hơn nhiều.
Tôi không chắc điều này có hoạt động với tất cả các phiên bản không, nhưng tôi đang sử dụng 5.5 với công cụ InnoDB.
SELECT TABLE_NAME,SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'your_db'
GROUP BY TABLE_NAME;
Đó là tất cả những gì bạn cần.
mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
Quy trình được lưu trữ này liệt kê các bảng, đếm các bản ghi và tạo ra tổng số bản ghi ở cuối.
Để chạy nó sau khi thêm thủ tục này:
CALL `COUNT_ALL_RECORDS_BY_TABLE` ();
-
Thủ tục:
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
Cách đơn giản:
SELECT
TABLE_NAME, SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{Your_DB}'
GROUP BY TABLE_NAME;
Ví dụ kết quả:
+----------------+-----------------+
| 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 |
+----------------+-----------------+
Có một chút hack / giải pháp cho vấn đề ước tính này.
Auto_Increment - vì một số lý do, điều này trả về số hàng chính xác hơn nhiều cho cơ sở dữ liệu của bạn nếu bạn có chế độ tăng tự động được thiết lập trên các bảng.
Tìm thấy điều này khi khám phá lý do tại sao hiển thị thông tin bảng không khớp với dữ liệu thực tế.
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)
Sau đó, bạn có thể dễ dàng sử dụng PHP hoặc bất cứ điều gì để trả về tối đa 2 cột dữ liệu để đưa ra "ước tính tốt nhất" cho số lượng hàng.
I E
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;
Tự động tăng sẽ luôn tắt +1 * (số bảng), nhưng ngay cả với 4.000 bảng và 3 triệu hàng, điều đó chính xác 99,9%. Tốt hơn nhiều so với các hàng ước tính.
Cái hay của điều này là số hàng được trả về trong Performance_schema cũng bị xóa cho bạn, bởi vì lớn nhất không hoạt động trên null. Điều này có thể là một vấn đề nếu bạn không có bảng với tăng tự động, mặc dù.
Bạn có thể thử điều này. Nó đang làm việc tốt cho tôi.
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;
Nếu bạn sử dụng cơ sở dữ liệu information_schema, bạn có thể sử dụng mã mysql này (phần trong đó làm cho truy vấn không hiển thị các bảng có giá trị null cho các hàng):
SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
Truy vấn sau đây tạo ra một truy vấn (nother) sẽ nhận giá trị đếm (*) cho mỗi bảng, từ mọi lược đồ, được liệt kê trong information_schema.tables. Toàn bộ kết quả của truy vấn được hiển thị ở đây - tất cả các hàng được kết hợp với nhau - bao gồm một câu lệnh SQL hợp lệ kết thúc bằng dấu chấm phẩy - không có 'liên kết' lơ lửng. Liên minh lơ lửng được tránh bằng cách sử dụng một liên minh trong truy vấn dưới đây.
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);';
Đây là những gì tôi làm để có được số lượng thực tế (không sử dụng lược đồ)
Nó chậm hơn nhưng chính xác hơn.
Đó là một quá trình hai bước tại
Nhận danh sách các bảng cho db của bạn. Bạn có thể lấy nó bằng cách sử dụng
mysql -uroot -p mydb -e "show tables"
Tạo và gán danh sách các bảng cho biến mảng trong tập lệnh bash này (được phân tách bằng một khoảng trắng giống như trong mã bên dưới)
array=( table1 table2 table3 )
for i in "${array[@]}"
do
echo $i
mysql -uroot mydb -e "select count(*) from $i"
done
Chạy nó:
chmod +x script.sh; ./script.sh
Thêm một tùy chọn: đối với không phải InnoDB, nó sử dụng dữ liệu từ information_schema.TABLES (vì nó nhanh hơn), đối với InnoDB - chọn đếm (*) để có được số đếm chính xác. Ngoài ra nó bỏ qua quan điểm.
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;
Nếu cơ sở dữ liệu của bạn có nhiều bảng InnoDB lớn, đếm tất cả các hàng có thể mất nhiều thời gian hơn.
Đây là cách tôi đếm BẢNG và TẤT CẢ HỒ SƠ bằng 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.";
Poster muốn đếm hàng mà không đếm, nhưng không chỉ định công cụ bảng nào. Với InnoDB, tôi chỉ biết một cách, đó là đếm.
Đây là cách tôi chọn khoai tây:
# 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"
}
Tôi không khẳng định gì về điều này ngoài việc đây là một cách thực sự xấu nhưng hiệu quả để có bao nhiêu hàng tồn tại trong mỗi bảng trong cơ sở dữ liệu bất kể công cụ bảng và không phải có quyền cài đặt các thủ tục được lưu trữ và không cần phải cài đặt ruby hoặc php. Vâng, nó rỉ sét. Có nó tính. đếm (*) là chính xác.
Dựa trên câu trả lời của @ Nathan ở trên, nhưng không cần phải "xóa liên kết cuối cùng" và với tùy chọn sắp xếp đầu ra, tôi sử dụng SQL sau. Nó tạo ra một câu lệnh SQL khác mà sau đó chỉ chạy:
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
Bạn cần một giá trị đủ lớn của group_concat_max_len
biến máy chủ nhưng từ MariaDb 10.2.4, nó sẽ mặc định là 1M.
Mã dưới đây tạo ra truy vấn chọn cho tất cả các câu chuyện. Chỉ cần xóa "UNION ALL" cuối cùng, chọn tất cả kết quả và dán cửa sổ truy vấn mới để chạy.
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'
Nếu bạn muốn con số chính xác, hãy sử dụng tập lệnh ruby sau đây. Bạn cần Ruby và RubyGems.
Cài đặt các viên đá quý sau:
$> gem install dbi
$> gem install dbd-mysql
Tệp: 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
Quay trở lại dòng lệnh:
$> ruby count_table_records.rb
Đầu ra:
Table users has 7328974 rows.
Nếu bạn biết số lượng bảng và tên của chúng và giả sử mỗi bảng có khóa chính, bạn có thể sử dụng liên kết chéo kết hợp với COUNT(distinct [column])
để lấy các hàng đến từ mỗi bảng:
SELECT
COUNT(distinct t1.id) +
COUNT(distinct t2.id) +
COUNT(distinct t3.id) AS totalRows
FROM firstTable t1, secondTable t2, thirdTable t3;
Đây là một ví dụ SQL Fiddle .