ThinkPHP5查询当前表引擎,以及InnoDB表引擎下count(*)查询效率低的问题

Posted 何效名的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThinkPHP5查询当前表引擎,以及InnoDB表引擎下count(*)查询效率低的问题相关的知识,希望对你有一定的参考价值。


 

今天新开发的功能上线之后出现了查询效率极其低下的问题,查询日志后发现问题出在代码内的大量的count()查询上,最严重时一条简单的count()查询执行时间长达120多秒!

针对这个问题请教前辈后被告知原因:InnoDB引擎下的count()语句会在实时查询表中的所有数据后返回总数所以效率较低,而MyISAM引擎则是直接返回表内存储的行记录信息所以效率较高。因为我本地的数据库引擎为MyISAM而线上的阿里云数据库服务器引擎为InnoDB所以出现了这种本地环境与线上环境查询效率差距极大的问题。

并且前辈也给出了指导意见:因为InnoDB引擎的主键索引通常为聚簇索引,为了保证效率可以新建一个辅助索引用于为count()查询指定字段。经尝试后使用新的辅助索引字段来进行count()查询效率确实大大提升。

 


 

这里附上查询当前表引擎并判断是使用主键字段还是使用辅助索引字段进行count()查询的相关代码。

框架使用的是Thinkphp5,可以根据自己的状况自行调整代码。

function xmsb_getCountField($tableName)
{
    $dataBase = config(‘database.database‘);
    
    $tableDDL = Db::query("SHOW TABLE STATUS FROM `{$dataBase}` WHERE name = ‘{$tableName}‘"); // 获取表信息
    $engine = strtolower($tableDDL[0][‘Engine‘]); // 取得表引擎信息
    
    // 取得主键字段
    $pk = DB::getTableInfo($tableName, ‘pk‘);
    if(is_array($pk)) $pk = $pk[0];
    
    // 若表引擎为InnoDB则判断是否存在非主键索引
    if($engine == ‘innodb‘)
    {
        $indexs = Db::query("SHOW INDEX FROM {$tableName}");
        $key = $pk;
        foreach($indexs as $index)
        {
            // 若存在非主键索引,则返回该索引对应的字段
            if($index[‘Key_name‘] != ‘PRIMARY‘)
            {
                $key = $index[‘Column_name‘];
                break;
            }
        }
        
        return $key;
    }
    else
    {
        // 非InnoDB引擎则直接返回主键字段
        return $pk;
    }
}

$count = Db::name(‘数据表名‘) -> count(xmsb_getCountField(‘完整数据表名‘));

以上是关于ThinkPHP5查询当前表引擎,以及InnoDB表引擎下count(*)查询效率低的问题的主要内容,如果未能解决你的问题,请参考以下文章

mysql修改数据库的存储引擎(InnoDB)

存储引擎:MyISAM和InnoDB区别

mysql数据库引擎innodb的主索引文件和表文件分开吗?如果不分开,那怎么查询?

MySQL存储引擎MyISAM与InnoDB

mysql innodb存储引擎和myisam引擎

《MySQL系列-InnoDB引擎13》文件-参数文件