记一次主键查询乱序
前言
今天日常开发中,一条简单的不能再简单的查询,却莫名出现了主键乱序的情况,虽然加了order by
之后完美解决,但是还是想究其原因。
复现一下
表结构:
1 | CREATE TABLE `tb_test` ( |
插入数据(多插入几条数据,确保使用索引比全表扫描快,这样才会使用到索引 )
1 | INSERT INTO `tb_test` (`id`, `room_id`, `user_id`, `amount`) VALUES (1, 1, 1, 99.00); |
大概就构成了这样一个表
id | room_id | user_id | amount |
---|---|---|---|
1 | 1 | 1 | 99.00 |
2 | 1 | 4 | 80.00 |
3 | 1 | 2 | 28.00 |
4 | 2 | 2 | 77.00 |
5 | 2 | 1 | 66.00 |
6 | 2 | 5 | 98.00 |
7 | 3 | 1 | 55.00 |
8 | 3 | 3 | 98.00 |
9 | 3 | 2 | 66.00 |
执行SQL查询room_id
为1的记录SELECT * FROM tb_test where room_id = 1
,根据猜想,查询出来的记录应该为:
id | room_id | user_id | amount |
---|---|---|---|
1 | 1 | 1 | 99.00 |
2 | 1 | 4 | 80.00 |
3 | 1 | 2 | 28.00 |
然而实际上是:
id | room_id | user_id | amount |
---|---|---|---|
1 | 1 | 1 | 99.00 |
3 | 1 | 2 | 28.00 |
2 | 1 | 4 | 80.00 |
可以看出,查询的时候主键乱序了,查询的结果是根据user_id
排序的,而非安装原来的主键排序
猜想
tb_test
以room_id
和user_id
建立了索引,查询的时候使用了room_id = 1
的查询条件,复合索引的最左匹配原则,所以使用了索引tb_test_room_id_user_id_index
进行查询。
证明
使用EXPLAIN
命令分析一下上述SQL:EXPLAIN SELECT * FROM tb_test where room_id = 1
根据结果可知,确实使用了索引tb_test_room_id_user_id_index
,而索引中,默认使用room_id
和user_id
进行排序,所以就有了主键乱序的情况。
解决
如文章开头所讲,添加order by
即可,在所有你期望有顺序的查询中,都应该加上order by
来进行排序,以避免上述情况。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 顾澜的技术小站!
评论
GitalkValine