如何使用 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"索引有时速度加倍。
我在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"索引有时速度加倍。