【问题标题】:Most efficient way to get table row count获取表格行数的最有效方法
【发布时间】:2009-06-01 04:30:23
【问题描述】:

我目前拥有一个包含超过 600 万行并且还在不断增长的数据库。我目前在做 SELECT COUNT(id) FROM table;为了向我的用户显示数字,但是数据库变得越来越大,除了能够显示数字之外,我不需要存储所有这些行。有没有办法选择要显示的 auto_increment 值,以便我可以清除数据库中的大部分行?使用LAST_INSERT_ID() 似乎不起作用。

【问题讨论】:

  • 詹姆斯,您尝试过其他解决方案吗?他们似乎更好......
  • 如果您从未删除过记录,那么 auto_increment 将是正确的,否则它会被自表诞生以来删除的记录数所抵消。
  • 只是为了清楚区别,获取行数告诉您现在有多少行。如果您希望计数包括曾经存在但随后被删除的行,则需要 auto_increment (尽管这也将包括仅存在于回滚而不是提交的事务中的行)。
  • 或者,如果有人硬编码了一个高于某些插入的当前 auto_increment 的值,您也会跳过一些。我想说 auto_increment 并不是一种真正值得信赖的计数方式。

标签: mysql sql count


【解决方案1】:

以下是查找表的下一个AUTO_INCREMENT 值的最高效方法。即使在包含数百万个表的数据库上,这也很快,因为它不需要查询可能很大的 information_schema 数据库。

mysql> SHOW TABLE STATUS LIKE 'table_name';
// Look for the Auto_increment column

但是,如果您必须在查询中检索此值,则必须转到 information_schema 数据库。

SELECT `AUTO_INCREMENT`
FROM   INFORMATION_SCHEMA.TABLES
WHERE  TABLE_SCHEMA = 'DatabaseName'
AND    TABLE_NAME   = 'TableName';

【讨论】:

  • 这就像宣传的那样工作(与 LAST_INSERT_ID 答案相反)并且非常快。
  • 这应该被选为这个问题的正确答案。这种方法效率更高,不需要挖掘可能对共享 mySQL 服务器造成负担的 information_schema.tables。 @thinkswan 伟大而简单的解决方案。
  • 这个问题不是要找MySQL解决方案,而不是PHP解决方案吗?
  • 这不能回答问题;它不是 MySQL 语法代码。你需要一个 PHP 预处理器,例如你不能在 DML 脚本中使用它。
  • 为什么你觉得有必要用 PHP 代码混淆你的答案?问题是关于 SQL 的。
【解决方案2】:

如果只是获取记录(行)的数量,我建议使用:

SELECT TABLE_ROWS
FROM information_schema.tables 
WHERE table_name='the_table_you_want' -- Can end here if only 1 DB 
  AND table_schema = DATABASE();      -- See comment below if > 1 DB

(至少对于 MySQL)。

【讨论】:

  • 这对于大型数据库来说是一个糟糕的解决方案。仅此查询就可能需要整整几分钟才能完成,因为它必须搜索整个 information_scheme.tables 表。对于拥有数千个运行数据库的客户端的虚拟主机,该单个表变得非常大。
  • 你可能想添加AND table_schema=DATABASE(),因为多个数据库可以有一个同名的表
  • @thinkswan,我敢打赌,通过添加 table_schema 限制,此查询的性能会大幅提升。
  • 这会返回 autoincrement_id 值还是表中的行数?我认为这应该是SELECT AUTO_INCREMENT FROM...
  • @jjmontes 是正确的 - TABLE_ROWSAUTO_INCREMENT 是不同的统计数据,并且 OP 问题具有误导性。 TABLE_ROWS = 表中的行,AUTO_INCREMENT = auto inc 计数器的值。我可以有一个只有一行的表,但将 AUTO_INCREMENT 设置为 1,000,000。 (例如,如果您从表中删除前 999,999 行,这很容易发生!)。 AUTO_INCREMENT 值实际上是用户可配置的,因此永远不要假设行数和 auto inc 是同一件事,这一点非常重要。 TABLE_ROWS !== AUTO_INCREMENT
【解决方案3】:

试试这个

执行这条 SQL:

SHOW TABLE STATUS LIKE '<tablename>'

并获取字段Auto_increment的值

【讨论】:

    【解决方案4】:

    我不确定为什么没有人提出以下建议。这将仅使用 SQL 获得 auto_increment 值(无需使用 PHP 的 mysql_fetch_array):

    SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = 'table'
    

    【讨论】:

    • 这是迄今为止最好的答案,但有一点需要注意。我建议进行编辑,但对于那些同时看到这一点的人:对于包含具有相同表名的多个数据库的服务器,您也应该包括 AND TABLE_SCHEMA='database'。
    【解决方案5】:

    如果您通过编写选择查询直接获取最大数量,那么您的查询可能会给出错误的值。 例如如果您的表有 5 条记录,那么您的增量 id 将为 6,如果我删除第 5 条记录,那么您的表有 4 条记录,最大 id 为 4,在这种情况下,您将获得 5 作为下一个增量 id。 为此,您可以从 mysql 定义本身获取信息。通过在php中编写以下代码

    <?
    $tablename      = "tablename";
    $next_increment     = 0;
    $qShowStatus        = "SHOW TABLE STATUS LIKE '$tablename'";
    $qShowStatusResult  = mysql_query($qShowStatus) or die ( "Query failed: " . mysql_error() . "<br/>" . $qShowStatus );
    
    $row = mysql_fetch_assoc($qShowStatusResult);
    $next_increment = $row['Auto_increment'];
    
    echo "next increment number: [$next_increment]";
    ?>
    

    【讨论】:

      【解决方案6】:

      SELECT id FROM table ORDER BY id DESC LIMIT 1 可以返回最大 id 而不是自动递增 id。在某些情况下两者是不同的

      【讨论】:

        【解决方案7】:

        如果您没有“显示状态”的权限,那么, 最好的选择是创建两个触发器和一个新表,以保留十亿记录表的行数。

        例子:

        TableA >> 十亿条记录
        表B >> 1列1行

        每当 TableA(InsertTrigger) 上有插入查询时,将 TableB 的行值增加 1
        每当 TableA(DeleteTrigger) 有删除查询时,将 TableB 中的行值减 1

        【讨论】:

          【解决方案8】:

          在 information_schema 建议旁边,这个:

          SELECT id FROM table ORDER BY id DESC LIMIT 1
          

          也应该很快,只要 id 字段上有一个索引(我相信 auto_increment 必须是这种情况)

          【讨论】:

          • 您还应该在末尾添加一个 LIMIT 1 ,这样它就不会仅仅为此检索每个 id。
          • 这并不一定会给您最后的自动增量值,因为您可以在 auto_increment'ed 列中插入/更新特定值
          • 其实 SELECT MAX(id) FROM table 应该使用更少的内存
          • 我认为如果这个答案无效,应该删除它。
          • 这只有在没有进行任何更改时才有效——即没有删除
          【解决方案9】:
          $next_id = mysql_fetch_assoc(mysql_query("SELECT MAX(id) FROM table"));
          $next_id['MAX(id)']; // next auto incr id
          

          希望对你有帮助:)

          【讨论】:

          • 如果上一条记录被删除,这将不起作用,这将返回存在的最大行id,但不是下一个要自动递增的id,
          【解决方案10】:

          控制器

          SomeNameModel::_getNextID($this->$table)
          

          型号

          class SomeNameModel extends CI_Model{
          
          private static $db;
          
          function __construct(){
            parent::__construct();
            self::$db-> &get_instance()->db;
          }
          
          
          function _getNextID($table){
            return self::$db->query("SHOW TABLE STATUS LIKE '".$table."' ")->row()->Auto_increment;
          }
          
          ... other stuff code
          
          }
          

          【讨论】:

            【解决方案11】:

            这些答案似乎都不完全正确。我都试过了。这是我的结果。

            Sending query: SELECT count(*) FROM daximation
            91
            Sending query: SELECT Auto_increment FROM information_schema.tables WHERE table_name='daximation'
            96
            Sending query: SHOW TABLE STATUS LIKE 'daximation'
            98
            Sending query: SELECT id FROM daximation ORDER BY id DESC LIMIT 1
            97
            

            这是屏幕截图: https://www.screencast.com/t/s8c3trYU

            这是我的 PHP 代码:

            $query = "SELECT count(*) FROM daximation"; 
            $result = sendquery($query);
            $row = mysqli_fetch_row($result);
            debugprint( $row[0]);
            
            $query = "SELECT Auto_increment FROM information_schema.tables WHERE table_name='daximation'"; 
            $result = sendquery($query);
            $row = mysqli_fetch_row($result);
            debugprint( $row[0]);
            
            $query = "SHOW TABLE STATUS LIKE 'daximation'"; 
            $result = sendquery($query);
            $row = mysqli_fetch_row($result);
            debugprint( $row[10]);
            
            $query = "SELECT id FROM daximation ORDER BY id DESC LIMIT 1"; 
            $result = sendquery($query);
            $row = mysqli_fetch_row($result);
            debugprint( $row[0]);
            

            【讨论】:

              【解决方案12】:

              您不能只在单独的表中创建一条记录,或者使用名为“用户”的列并使用用户注册时最后插入的 id 更新它吗?

              然后您只需通过一个简单的查询来检查该字段。

              它可能很粗糙,但它会完美地工作。

              【讨论】:

                猜你喜欢
                • 2018-07-21
                • 2015-12-20
                • 1970-01-01
                • 2015-10-29
                • 1970-01-01
                • 1970-01-01
                • 2013-06-04
                • 2017-06-30
                • 1970-01-01
                相关资源
                最近更新 更多