如何使用 GROUPBY mysql 查询优化 COUNT?

How can I optimise COUNT with GROUPBY mysql query?

我在eustable和121中有5M条记录es table。我正在进行左连接,但 COUNT 查询使我的查询非常慢。我该如何优化它?

public static function getAllActiveEvaluationSymptomsWithNameForDataTable(){
    $queryBuilder = new Builder();

    $queryBuilder
        ->from(array('es' =>  static::class))
        ->leftJoin('EvaluationUserSymptom',  'es.id = eus.eb_evaluation_symptom_id','eus')
        ->columns('es.id, es.title, COUNT(eus.eb_evaluation_symptom_id) AS counts')
        ->groupBy('eus.eb_evaluation_symptom_id')
        ->where('es.is_active = 1');

    return  $queryBuilder;
}

带解释的原始查询:

EXPLAIN 
SELECT  es.id AS id, es.title AS title,
        COUNT(eus.eb_evaluation_symptom_id) AS counts,
        eus.date_created AS date_created
    FROM  eb_evaluation_symptom AS es
    LEFT JOIN  eb_evaluation_user_symptom AS eus
           ON es.id = eus.eb_evaluation_symptom_id
    WHERE  es.is_active = 1
    GROUP BY  eus.eb_evaluation_symptom_id;

解释的输出:

解释视觉视图:

这个 完整 table 扫描 计数造成了问题。

注意:所有 JOIN 和必要的列字段都有正确的索引。

尝试在连接前聚合:

SELECT es.id AS id, es.title AS title
  , coalesce(eus.counts, 0) as counts
  , eus.date_created
FROM eb_evaluation_symptom AS es 
LEFT JOIN 
 ( select eb_evaluation_symptom_id  
     , COUNT(*) AS counts
     , min(date_created) AS date_created -- or MAX?
   from eb_evaluation_user_symptom 
   GROUP BY eb_evaluation_symptom_id
 ) AS eus 
ON es.id = eus.eb_evaluation_symptom_id 
WHERE es.is_active = 1 ;

相关子查询可以是一种快速方法:

SELECT es.id, es.title,
      (select count(*)
       from eb_evaluation_user_symptom eus
       where es.id = eus.eb_evaluation_symptom_id
      ) as cnt
FROM eb_evaluation_symptom es  
WHERE es.is_active = 1 ;

为了性能,您需要 eb_evaluation_user_symptom(eb_evaluation_symptom_id) 上的索引。

eb_evaluation_symptom 上的索引不会有太大帮助,因为 table 太小了。

你有这些覆盖索引吗?

INDEX(eb_evaluation_symptom_id, date_created)
INDEX(is_active, id, title)

"Covering"索引有时速度加倍。