2025-10-31 07:15 广东
MySQL推出这个参数本来是好意,但容易好心办坏事……
DROP TABLE IF EXISTS users;CREATE TABLE users (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(50),gender CHAR(1), -- 'M' 或 'F'age INT,INDEX idx_gender (gender));
DELIMITER //CREATE PROCEDURE load_users(IN total INT)BEGINDECLARE i INT DEFAULT 1;WHILE i <= total DOINSERT INTO users(name, gender, age)VALUES (CONCAT('user_', i),IF(RAND() > 0.5, 'M', 'F'),FLOOR(20 + (RAND() * 30)));SET i = i + 1;END WHILE;END //DELIMITER ;
-- 开启 prefer_ordering_indexSET optimizer_switch = 'prefer_ordering_index=on';EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;-- 关闭 prefer_ordering_indexSET optimizer_switch = 'prefer_ordering_index=off';EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;
-- 开启 prefer_ordering_index SET optimizer_switch = 'prefer_ordering_index=on'; EXPLAIN SELECT gender, COUNT(*) FROM users GROUP BY gender;-- 关闭 prefer_ordering_index SET optimizer_switch = 'prefer_ordering_index=off'; EXPLAIN SELECT gender, COUNT(*) FROM users GROUP BY gender;mysql> SET optimizer_switch = 'prefer_ordering_index=on';Query OK, 0 rows affected (0.00 sec)mysql> EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------+| 1 | SIMPLE | users | NULL | index | NULL | idx_gender | 5 | NULL | 10 | 100.00 | NULL |+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------+1 row inset, 1 warning (0.00 sec)mysql> SET optimizer_switch = 'prefer_ordering_index=off';Query OK, 0 rows affected (0.00 sec)mysql> EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+| 1 | SIMPLE | users | NULL | ALL | NULL | NULL | NULL | NULL | 997227 | 100.00 | Using filesort |+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+1 row inset, 1 warning (0.00 sec)
写到这里,MySQL推出这个参数本来是好意,但是截至到目前,尚未得到在任何版本,智能化此问题的方案,对于业务和DBA来说,大部分情况选择的是关闭此选项,因为我们不能完全杜绝无可选择性下的数据和索引建立后,在遇到GROUP BY ORDER BY 情况下的错误索引的在这类语句上得使用。mysql> SET optimizer_switch = 'prefer_ordering_index=on';Query OK, 0 rows affected (0.00 sec)mysql> EXPLAIN SELECT gender, COUNT(*) FROM users GROUP BY gender;+----+-------------+-------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+| 1 | SIMPLE | users | NULL | index | idx_gender | idx_gender | 5 | NULL | 997227 | 100.00 | Using index |+----+-------------+-------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+1 row inset, 1 warning (0.04 sec)mysql>mysql> -- 关闭 prefer_ordering_indexmysql> SET optimizer_switch = 'prefer_ordering_index=off';Query OK, 0 rows affected (0.00 sec)mysql> EXPLAIN SELECT gender, COUNT(*) FROM users GROUP BY gender;+----+-------------+-------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+| 1 | SIMPLE | users | NULL | index | idx_gender | idx_gender | 5 | NULL | 997227 | 100.00 | Using index |+----+-------------+-------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+1 row inset, 1 warning (0.00 sec)
作者介绍
刘华阳,20年经历风霜雨打的 DBA,5年的 DBA 架构和团队管理经验,只要是数据库都喜欢学习。PostgreSQL ACE,MongoDB 狂热者,10年的 MYSQL 工作经验,现在在玩 POLARDB 与时俱进。
