获取MySQL数据库中所有表的记录计数


Answers:


416
SELECT SUM(TABLE_ROWS) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE TABLE_SCHEMA = '{your_db}';

不过请从文档中注意:对于InnoDB表,行数只是 SQL优化中使用的粗略估计。您需要使用COUNT(*)进行精确计数(这更昂贵)。


266
或者,如果要为每个表:SELECT table_name,则TABLE_ROWS FROMINFORMATION_SCHEMA。TABLESWHERE TABLE_SCHEMA ='{your_db}';
TheSoftwareJedi

5
还有其他获取table_row和table_name的方法吗?因为我想要准确的结果而不是粗略的估计。谢谢。
krunal shah 2011年

3
@krunalshah,这是InnoDB的限制之一。有关更多信息,请参见dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html,InnoDB表的限制部分。您可以始终使用SELECT COUNT(*)FROM t,但是速度较慢
标记

2
射术,不,不是。count(*)(或更实际的是count(id))是mysql用来计算其行数的不是吗?无论如何,我都对其进行了测试,并为count()调用获得了更大的数量,无论它值多少。
codygman

2
在INFORMATION_SCHEMA中选择TABLE_NAME,SUM(TABLE_ROWS)N。在TABLE_SCHEMA ='{your_db}'的情况下,TABLE_NAME分组;
PiyusG 2014年

175

你也许可以把一些东西连同表的表。我从未做过,但是看起来它有一列TABLE_ROWS和一列TABLE NAME

要获取每个表的行,可以使用如下查询:

SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';

4
还有其他获取table_row和table_name的方法吗?因为我想要准确的结果而不是粗略的估计。谢谢。
krunal shah 2011年

1
正如kuranl所提到的,这只是返回一个估算值,运行几次可能会返回不同的结果
Kris

每次运行此查询时,具有至少约250条记录的表似乎报告的行数不同。
亚瑟

糟糕...希望我能像昨天一样早已看到“估计”一词!答案不应该被拒绝吗?OP并没有要求“估计”,并且认为他可能需要一个估计似乎很可笑。“估计”能否挽救像我这样的栗色人,使他们免于错过“估计”?
Kreeverp 2015年

111

像@Venkatramanan和其他人一样,我发现INFORMATION_SCHEMA.TABLES不可靠(使用InnoDB,MySQL 5.1.44),即使我在静止的表上每次运行,其行计数也不同。这是一种相对大胆(但灵活/适应)的生成大型SQL语句的方式,您可以将其粘贴到新查询中,而无需安装Ruby gems和其他东西。

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)

2
谢谢,我希望我不必安装任何插件/宝石即可获得准确的计数。
bradvido 2014年

如果数据库中有大量表,则执行时间太长。
ollamh

1
在删除最后一个UNION以通过表计数desc获取顺序之后,在生成的查询的末尾添加“ select * from(“开头,“)作为exact_row_count desc的输出顺序”)
Raghavendra

要排除视图:WHERE table_schema =' my_schema '和TABLE_TYPE LIKE'%TABLE%'
Watson

38

我只是跑:

show table status;

这将为您提供每个表的行数以及其他信息。我曾经使用上面选择的答案,但这要容易得多。

我不确定这是否适用于所有版本,但是我将5.5与InnoDB引擎一起使用。


5
不幸的是,如果您使用的是InnoDB,则此方法与上述其他方法一样会遭受相同的错误。例如,我有一个大约有65,000行的InnoDB表,但是这里的这些方法报告它的表范围从350,000到780,000以上。
PeterToTheThird 2014年

对于只有几行的数据库,它是相当准确的(或者足够准确以满足我的需求)。它为我的表提供了1086行,其中COUNT(*)报告了904行。
Magne 2014年

到目前为止最好的答案。我使用InnoDB,但只需要一个快速命令即可知道数量级。
Nemo

认真地,希望这被接受。不使用InnoDB,并给我确切的答案。
Kolob Canyon

1
行号不正确,但是如果您没有从此类表中删除任何行,则“ Auto_increment”可以为您提供准确的号。
Peter T.

13
 SELECT TABLE_NAME,SUM(TABLE_ROWS) 
 FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_SCHEMA = 'your_db' 
 GROUP BY TABLE_NAME;

这就是您所需要的。


1
产生估计的表行-与“ mysql_num_rows($ tableresult)比较”
Kreeverp

1
这实际上是最好的答案!也是从mysql cli执行的更简单的方法:mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
loretoparisi

11

该存储过程列出了表,对记录进行了计数,最后产生了记录总数。

要在添加此过程后运行它:

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

8

简单方法:

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

4

对于此估算问题,有一些解决方法。

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个表和300万行,准确度仍为99.9%。比估计的行好得多。

这样做的好处是,也会为您删除performance_schema中返回的行数,因为在最大的null值上不起作用。但是,如果您没有带自动递增功能的表,则可能会出现问题。


3

你可以试试看 对我来说很好。

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

如果使用数据库information_schema,则可以使用以下mysql代码(where部分使查询不显示行的值为空的表):

SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0

1

以下查询生成一个(另一个)查询,该查询将从information_schema.tables中列出的每个模式中的每个表获取count(*)的值。此处显示的查询的整个结果-所有行加在一起-包含以分号结尾的有效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);';

1

这就是我要获取的实际数量(不使用架构)

速度较慢,但​​更准确。

这是一个两步过程

  1. 获取数据库的表列表。你可以用

    mysql -uroot -p mydb -e "show tables"
  2. 在此bash脚本中创建表列表并将其分配给数组变量(如下面的代码一样,用一个空格分隔)

    array=( table1 table2 table3 )
    
    for i in "${array[@]}"
    do
        echo $i
        mysql -uroot mydb -e "select count(*) from $i"
    done
  3. 运行:

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

1

另一种选择:对于非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表,则计算所有行可能需要更多时间。


0

这就是我使用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.";

如果您将忽略数据,为什么不使用count(*)?
Svetoslav Marinov,

0

海报想要行计数而不计数,但是没有指定哪个表引擎。使用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(*)是准确的。


0

基于上面的@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。


0

下面的代码生成所有故事的select查询。只需删除最后一个“ 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'

-1

如果您想要确切的数字,请使用以下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.

-4

如果您知道表的数目及其名称,并假设它们每个都有主键,则可以结合使用交叉联接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示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.