mysql> show warnings\G *************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select `rep`.`t_date`.`id` AS `id`, `rep`.`t_date`.`create_time` AS `create_time`, `rep`.`t_date`.`padding` AS `padding` from `rep`.`t_date` where (cast(`create_time` as date) = '2024-06-01')
索引字段上的函数运算还会以其他形式出现,比如下面这两个SQL。
1 2
select * from t1 where b+0 = ?; select * from t1 where c||'' = ?;
mysql> explain select * from tab where phone=13512345678; +----+-------------+-------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | tab | ALL | idx_phone | NULL | NULL | NULL | 1 | 100.00 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 3 warnings (0.00 sec)
mysql> show warnings; +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Warning | 1739 | Cannot use ref access on index 'idx_phone' due to type or collation conversion on field 'phone' | | Warning | 1739 | Cannot use range access on index 'idx_phone' due to type or collation conversion on field 'phone' | | Note | 1003 | /* select#1 */ select `test`.`tab`.`id` AS `id`,`test`.`tab`.`phone` AS `phone`,`test`.`tab`.`phone2` AS `phone2`,`test`.`tab`.`create_time` AS `create_time`,`test`.`tab`.`create_time2` AS `create_time2` from `test`.`tab` where (`test`.`tab`.`phone` = 13512345678) | +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 3 rows in set (0.00 sec)
mysql> explain select * from tab where create_time = date(now()); +----+-------------+-------+------+----------------+------+---------+------+------+----------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------+----------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | tab | ALL | idx_createtime | NULL | NULL | NULL | 1 | 100.00 | Using where | +----+-------------+-------+------+----------------+------+---------+------+------+----------+-------------+ 1 row in set, 3 warnings (0.00 sec)
mysql> show warnings; +---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Warning | 1739 | Cannot use ref access on index 'idx_createtime' due to type or collation conversion on field 'create_time' | | Warning | 1739 | Cannot use range access on index 'idx_createtime' due to type or collation conversion on field 'create_time' | | Note | 1003 | /* select#1 */ select `test`.`tab`.`id` AS `id`,`test`.`tab`.`phone` AS `phone`,`test`.`tab`.`phone2` AS `phone2`,`test`.`tab`.`create_time` AS `create_time`,`test`.`tab`.`create_time2` AS `create_time2` from `test`.`tab` where (`test`.`tab`.`create_time` = <cache>(cast(now() as date))) | +---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 3 rows in set (0.00 sec)
情况3:字段类型为数字,传入字符串类型的参数,是否也会导致索引不可用呢? 我们来测试一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
mysql> explain select * from tab where phone2 = '13512345678'; +----+-------------+-------+------+---------------+------------+---------+-------+------+----------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------+---------------+------------+---------+-------+------+----------+-----------------------+ | 1 | SIMPLE | tab | ref | idx_phone2 | idx_phone2 | 9 | const | 1 | 100.00 | Using index condition | +----+-------------+-------+------+---------------+------------+---------+-------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)
mysql> show warnings\G *************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select `test`.`tab`.`id` AS `id`,`test`.`tab`.`phone` AS `phone`, `test`.`tab`.`phone2` AS `phone2`,`test`.`tab`.`create_time` AS `create_time`, `test`.`tab`.`create_time2` AS `create_time2` from `test`.`tab` where (`test`.`tab`.`phone2` = 13512345678)
mysql> show warnings\G *************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select `test`.`tab`.`id` AS `id`,`test`.`tab`.`phone` AS `phone`, `test`.`tab`.`phone2` AS `phone2`,`test`.`tab`.`create_time` AS `create_time`, `test`.`tab`.`create_time2` AS `create_time2` from `test`.`tab` where (`test`.`tab`.`create_time2` = TIMESTAMP'2023-01-01 00:00:00')
执行explain extended后查看warnings(注:8.0已经不支持explain extended了),发现SQL中有字符集转换的操作convert(b.uuid using utf8mb4)。
1 2 3 4 5 6 7 8 9 10 11 12
mysql> explain extended select b.* from patients a, funds b where a.create_at != "0000-00-00 00:00:00" and a.uuid=b.uuid mysql> show warnings select * from patients a join funds b where((a.create_at <> '0000-00-00 00:00:00') and(a.uuid= convert(b.uuid using utf8mb4)))
explain extended SELECT b.* FROM (select convert(uuid using utf8) COLLATE utf8_unicode_ci as uuid from patients where project_create_at != "0000-00-00 00:00:00") a, funds b WHERE a.uuid = b.uuid
mysql> explain select * from t_1 straight_join t_2 on t_1.uuid = t_2.uuid; +----+-------------+-------+------+---------------+-----------+---------+--------------+------+----------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------+---------------+-----------+---------+--------------+------+----------+-----------------------+ | 1 | SIMPLE | t_1 | ALL | idx_uuid1 | NULL | NULL | NULL | 1 | 100.00 | Using where | | 1 | SIMPLE | t_2 | ref | idx_uuid2 | idx_uuid2 | 131 | rep.t_1.uuid | 1 | 100.00 | Using index condition | +----+-------------+-------+------+---------------+-----------+---------+--------------+------+----------+-----------------------+ 2 rows in set, 2 warnings (0.00 sec)
mysql> show warnings\G *************************** 1. row *************************** Level: Warning Code: 1739 Message: Cannot use ref access on index 'idx_uuid1' due to type or collation conversion on field 'uuid' *************************** 2. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select `rep`.`t_1`.`id` AS `id`,`rep`.`t_1`.`uuid` AS `uuid`, `rep`.`t_1`.`padding` AS `padding`,`rep`.`t_2`.`id` AS `id`, `rep`.`t_2`.`uuid` AS `uuid`,`rep`.`t_2`.`padding` AS `padding` from `rep`.`t_1` straight_join `rep`.`t_2` where (`rep`.`t_1`.`uuid` = `rep`.`t_2`.`uuid`)
mysql> explain select * from t_2 straight_join t_1 on t_1.uuid = t_2.uuid; +----+-------------+-------+------+---------------+------+---------+------+------+----------+--------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+----------+--------------------------------------------+ | 1 | SIMPLE | t_2 | ALL | idx_uuid2 | NULL | NULL | NULL | 1 | 100.00 | NULL | | 1 | SIMPLE | t_1 | ALL | idx_uuid1 | NULL | NULL | NULL | 1 | 100.00 | Using where; Using join buffer (hash join) | +----+-------------+-------+------+---------------+------+---------+------+------+----------+--------------------------------------------+ 2 rows in set, 3 warnings (0.00 sec)
mysql> show warnings\G *************************** 1. row *************************** Level: Warning Code: 1739 Message: Cannot use ref access on index 'idx_uuid1' due to type or collation conversion on field 'uuid' *************************** 2. row *************************** Level: Warning Code: 1739 Message: Cannot use range access on index 'idx_uuid1' due to type or collation conversion on field 'uuid' *************************** 3. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select `rep`.`t_2`.`id` AS `id`,`rep`.`t_2`.`uuid` AS `uuid`, `rep`.`t_2`.`padding` AS `padding`,`rep`.`t_1`.`id` AS `id`, `rep`.`t_1`.`uuid` AS `uuid`,`rep`.`t_1`.`padding` AS `padding` from `rep`.`t_2` straight_join `rep`.`t_1` where (`rep`.`t_1`.`uuid` = `rep`.`t_2`.`uuid`)
SELECT count(1) FROM car WHERE is_deleted = 0 AND (seller_id = 100 OR (creator = 200 AND seller_id = -1)) AND car_id NOT IN ( SELECT car_id FROM product WHERE product_type = 2 AND source = 2)
SELECT sum(a) FROM ( SELECT count(1) as a FROM car WHERE is_deleted = 0 AND car_id NOT IN ( SELECT car_id FROM product WHERE product_type = 2 AND source = 2) AND (seller_id = 100) union all SELECT count(1) as a FROM car WHERE is_deleted = 0 AND car_id NOT IN (SELECT car_id FROM product WHERE product_type = 2 AND source = 2) AND creator = 1000 AND seller_id = -1 ) t