mysql> EXPLAIN SELECT*FROM t WHERE (a BETWEEN1AND1000) AND (b BETWEEN50000AND100000) ORDERBY b LIMIT 1; +----+-------------+-------+------------+-------+---------------+------+---------+------+-------+----------+------------------------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-------+------------+-------+---------------+------+---------+------+-------+----------+------------------------------------+ |1| SIMPLE | t |NULL|range| a,b | b |5|NULL|50128|1.00|Using index condition; Usingwhere| +----+-------------+-------+------------+-------+---------------+------+---------+------+-------+----------+------------------------------------+
这次优化器选择了索引b,而rows字段显示需要扫描的行数是50128:
扫描行数的估计值依然不准确;
MySQL选错了索引
force index
1 2 3 4 5 6
mysql> EXPLAIN SELECT*FROM t FORCE INDEX(a) WHERE (a BETWEEN1AND1000) AND (b BETWEEN50000AND100000) ORDERBY b LIMIT 1; +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+ |1| SIMPLE | t |NULL|range| a | a |5|NULL|1000|11.11|Using index condition; Usingwhere; Using filesort | +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+
修改语句
1 2 3 4 5 6 7
# 可以考虑修改语句,引导MySQL使用我们期望的索引 mysql> EXPLAIN SELECT*FROM t WHERE a BETWEEN1AND1000AND b BETWEEN50000AND100000ORDERBY b,a LIMIT 1; +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+ |1| SIMPLE | t |NULL|range| a,b | a |5|NULL|1000|11.11|Using index condition; Usingwhere; Using filesort | +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+
其他办法
新建一个更合适的索引
删除误用的索引
字符串索引
1 2 3 4 5 6 7 8 9 10 11 12
CREATETABLEuser( id BIGINT UNSIGNED PRIMARY KEY, name VARCHAR(64), email VARCHAR(64) ) ENGINE=InnoDB;
# 创建索引 ALTERTABLEuserADD INDEX index1(email); ALTERTABLEuserADD INDEX index2(email(6));
SELECT field_list FROM t WHERE id_card = REVERSE('input_id_card_string');
使用hash字段
1 2
ALTERTABLE t ADD id_card_crc INT UNSIGNED, ADD INDEX(id_card_crc); SELECT field_list FROM t WHERE id_card_crc=CRC32('input_id_card_string') AND id_card='input_id_card_string';