num INT(重複度高)CREATE TABLE test_test (
id INT(11) NOT NULL AUTO_INCREMENT,
num INT(11) NOT NULL DEFAULT 0,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- 存儲過程批量插入 10 萬條隨機數
DELIMITER //
CREATE PROCEDURE p_test(pa INT)
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE rand_num INT;
WHILE i < pa DO
SELECT CAST(RAND()*100 AS UNSIGNED) INTO rand_num;
INSERT INTO test_test(num) VALUES (rand_num);
SET i = i + 1;
END WHILE;
END//
DELIMITER ;
CALL p_test(100000);
SELECT DISTINCT num FROM test_test; SELECT num FROM test_test GROUP BY num;
結果:GROUP BY 快約 2 倍(MyISAM 全表掃描+臨時表排序,GROUP BY 內部優化更好)
ALTER TABLE test_test ADD INDEX num_index (num); -- 命令行開啟 Profiling 精確測量 SET PROFILING=1; SELECT DISTINCT num FROM test_test; SELECT num FROM test_test GROUP BY num; SHOW PROFILES;
結果(微秒級):
| 查詢 | 耗時 | 提升倍數 |
|---|---|---|
| DISTINCT (無索引) | ~78ms | 基準 |
| GROUP BY (無索引) | ~38ms | 2.05x |
| DISTINCT (有索引) | ~0.73ms | 107x |
| GROUP BY (有索引) | ~0.72ms | 53x |
DISTINCT 轉換為 GROUP BY 執行,但轉換過程有微小開銷-- 推薦寫法:語義清晰、性能最優 SELECT num FROM test_test GROUP BY num; -- 需要聚合統計時 SELECT num, COUNT(*) FROM test_test GROUP BY num; -- 避免寫法 SELECT DISTINCT num FROM test_test; -- 同義但略慢
EXPLAIN SELECT DISTINCT num FROM test_test; EXPLAIN SELECT num FROM test_test GROUP BY num;
兩者 Extra 欄均顯示 Using index(走覆蓋索引),type=index,執行計劃幾乎一致。
實測證明:去重查詢首選 GROUP BY,並務必在去重欄位建立索引。這是性能優化中投入產出比最高的操作之一。