Nhận số lượng bản ghi cho tất cả các bảng trong cơ sở dữ liệu MySQL


347

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?


1
Câu trả lời mở rộng cũng chính xác cho InnoDB: stackoverflow.com/questions/24707814/ cường
gwideman

1
Số lượng CHỌN (tên_bảng) TỪ THÔNG TIN_SCHema.TABLES WHERE TABLE_SCHema = 'YOU_DB' sẽ đưa ra số lượng bảng trong cơ sở dữ liệu của bạn
shasi kanth

Câu trả lời:


416
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).


266
hoặc, nếu bạn muốn cho mỗi bảng: CHỌN tên_bảng, TABLE_lawS TỪ THÔNG TIN_SCHema.TABLES WHERE TABLE_SCHema = '{your_db}';
TheSoftwareJedi

5
Có cách nào khác để lấy tên_bảng và tên_bảng không? Bởi vì tôi muốn kết quả chính xác không ước tính thô. Cảm ơn bạn.
krunal shah

3
@krunalshah, Đây là một trong những hạn chế của InnoDB. Xem dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html , phần Hạn chế trên Bảng InnoDB, để biết thêm thông tin. Bạn luôn có thể sử dụng CHỌN QUỐC GIA (*) TỪ, tuy nhiên, chậm hơn rất nhiều
Đánh dấu

2
Jaitsu, không, không phải vậy. đếm (*) (hoặc đếm thực tế hơn (id)) là những gì mysql sử dụng để đếm hàng của nó phải không? Trong mọi trường hợp, tôi chỉ kiểm tra nó và nhận được một số lớn hơn cho cuộc gọi Count (), bất cứ điều gì có giá trị.
codygman

2
CHỌN TABLE_NAME, SUM (TABLE_lawS) N TỪ THÔNG TIN_SCHema.TABLES WHERE TABLE_SCHema = '{your_db}' của nhóm TABLE_NAME;
PiyusG

175

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**';

4
Có cách nào khác để lấy tên_bảng và tên_bảng không? Bởi vì tôi muốn kết quả chính xác không ước tính thô. Cảm ơn bạn.
krunal shah

1
như kuranl đã đề cập, điều này trả về chỉ là ước tính và có thể sẽ trả về các kết quả khác nhau khi chạy một vài lần
Kris

Các bảng có ít nhất ~ 250 bản ghi dường như báo cáo số lượng hàng khác nhau mỗi lần tôi chạy truy vấn này.
Arthur

Ooops ... ước gì tôi đã thấy từ "Ước tính" trước khi ra tay ... như ngày hôm qua! Không nên trả lời bị từ chối? Vì OP không yêu cầu "ước tính" và có vẻ ngớ ngẩn khi nghĩ rằng anh ta có thể muốn ước tính. "Ước tính" Có thể cứu maroon như tôi khỏi bỏ lỡ "ước tính"?
Kreeverp

111

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)

2
Cảm ơn, tôi đã hy vọng tôi sẽ không phải cài đặt bất kỳ plugin / đá quý nào để có được số lượng chính xác.
bradvido

Mất quá nhiều thời gian để thực thi trong trường hợp số lượng lớn các bảng trong cơ sở dữ liệu.
ollamh

1
thêm "select * from (" ở đầu và ") làm thứ tự đầu ra bởi precision_row_count desc" vào cuối truy vấn được tạo sau khi xóa UNION cuối cùng để nhận thứ tự theo bảng đếm desc
Raghavendra

Để loại trừ lượt xem: WHERE table_schema = ' my_schema ' và TABLE_TYPE THÍCH '% TABLE%'
Watson

38

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.


5
Thật không may, nếu bạn đang sử dụng InnoDB, cách tiếp cận này gặp phải sự không chính xác giống như các phương pháp khác được mô tả ở trên. Ví dụ: tôi có một bảng InnoDB có khoảng 65.000 hàng, tuy nhiên các phương thức này ở đây báo cáo rằng nó có khoảng từ 350.000 đến hơn 780.000.
PeterToTheThird

Đối với một DB có vài hàng, nó khá chính xác (hoặc, đủ chính xác cho nhu cầu của tôi). Nó đã cho tôi 1086 hàng cho một bảng mà COUNT (*) đã báo cáo 904 hàng.
Magne

Bởi câu trả lời tốt nhất. Tôi sử dụng InnoDB nhưng tôi chỉ cần một lệnh nhanh để biết thứ tự cường độ.
Nemo

Nghiêm túc, mong muốn điều này đã được chấp nhận. Không sử dụng InnoDB và cho tôi câu trả lời chính xác.
Hẻm núi Kolob

1
Số hàng không chính xác nhưng "Auto_increment" có thể cung cấp cho bạn số chính xác nếu bạn không xóa bất kỳ hàng nào khỏi các bảng như vậy.
Peter T.

13
 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.


1
tạo các hàng trong bảng ước tính - so sánh với "mysql_num_rows ($ tableresult)"
Kreeverp

1
Đó là câu trả lời tốt nhất thực sự! Ngoài ra, đơn giản hơn để được thực hiện từ mysql cli:mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
loretoparisi 20/03/18

11

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

8

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 |
+----------------+-----------------+

4

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ù.


3

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;

2

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

1

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);';

1

Đâ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

  1. 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"
  2. 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
  3. Chạy nó:

    chmod +x script.sh; ./script.sh

1

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.


0

Đâ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.";

Tại sao bạn không sử dụng tính (*) nếu bạn sẽ bỏ qua dữ liệu?
Svetoslav Marinov

0

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.


0

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_lenbiến máy chủ nhưng từ MariaDb 10.2.4, nó sẽ mặc định là 1M.


0

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'

-1

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.

-4

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 .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.