首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL SQL優化實戰:統計分類計數從1.34秒降至0.78秒的兩種寫法對比

     編輯:MySQL 綜合教學

GROUP BY計數優化:用條件聚合替換分組掃描

原始慢查詢

SELECT country, COUNT(*) FROM t1 GROUP BY country;
-- 157萬行,耗時1.34秒,Extra: Using temporary; Using filesort

優化方案一:條件COUNT(推薦)

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。

優化方案二:條件SUM

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 BYCOUNT條件SUM條件
執行時間1.34s0.78s0.86s
臨時表Using temporary無無
文件排序Using filesort無無
掃描行數1,573,3821,573,3821,573,382

適用場景與擴展

  • 固定分類值統計(如:訂單狀態、用戶等級、地區分布)
  • 分類數<20時效果最佳,超過建議物化視圖或Summary Table
  • 可結合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;

核心結論

  1. 固定分類統計優先用條件聚合,避免GROUP BY產生臨時表與排序
  2. 2. COUNT(expr OR NULL)比SUM(expr)略快,語義更清晰 3. 結合覆蓋索引INDEX(country)可再提升3-5倍 4. 大分類場景改用Summary Table定時刷新
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved