SELECT country, COUNT(*) FROM t1 GROUP BY country; -- 157萬行,耗時1.34秒,Extra: Using temporary; Using filesort
SELECT COUNT(country='africa' OR NULL) AS africa, COUNT(country='america' OR NULL) AS america, COUNT(country='china' OR NULL) AS china FROM t1; -- 耗時0.78秒,Extra: 無臨時表、無filesort
原理:COUNT(expr)只統計非NULL值,condition OR NULL滿足條件返回true(非NULL),不滿足返回NULL。
SELECT SUM(country='africa') AS africa, SUM(country='america') AS america, SUM(country='china') AS china FROM t1; -- 耗時0.86秒,同樣消除臨時表
差異:MySQL中布爾值true=1、false=0,SUM直接累加。COUNT版本CPU開銷略低。
| 指標 | GROUP BY | COUNT條件 | SUM條件 |
|---|---|---|---|
| 執行時間 | 1.34s | 0.78s | 0.86s |
| 臨時表 | Using temporary | 無 | 無 |
| 文件排序 | Using filesort | 無 | 無 |
| 掃描行數 | 1,573,382 | 1,573,382 | 1,573,382 |
WHERE縮小掃描範圍:WHERE create_time > '2024-01-01'-- 預備語句動態構建
SET @sql = (
SELECT GROUP_CONCAT(
CONCAT('COUNT(country=', QUOTE(country), ' OR NULL) AS ', country)
) FROM (SELECT DISTINCT country FROM t1) t
);
SET @sql = CONCAT('SELECT ', @sql, ' FROM t1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
GROUP BY產生臨時表與排序COUNT(expr OR NULL)比SUM(expr)略快,語義更清晰
3. 結合覆蓋索引INDEX(country)可再提升3-5倍
4. 大分類場景改用Summary Table定時刷新