0%

联合索引的排序

联合索引的多字段排序的时候,是不可以夸字段排序,首字段也不能取范围的值。

表结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE `rank` (
`fetch_hour` int(10) NOT NULL DEFAULT '0' COMMENT '',
`times` tinyint(4) NOT NULL DEFAULT '1' COMMENT '',
`uid` varchar(64) NOT NULL DEFAULT '' COMMENT '',
`live_id` varchar(64) NOT NULL DEFAULT '' COMMENT '',
`reward` bigint(20) NOT NULL COMMENT '',
`rank` int(10) NOT NULL COMMENT '',
`shop_tags` varchar(255) DEFAULT '' COMMENT '',
`rank_type` tinyint(4) NOT NULL DEFAULT '12' COMMENT '',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`rank_type`,`fetch_hour`,`times`,`uid`),
KEY `rank_type_fetch_hour` (`rank_type`,`fetch_hour`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='';

执行:explain select * from rank where fetch_hour= '2021022511' and rank_type=12 order by times,uid` desc limit 1;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"data":
[
{
"id": 1,
"select_type": "SIMPLE",
"table": "rank",
"partitions": null,
"type": "ref",
"possible_keys": "PRIMARY,rank_type_fetch_hour",
"key": "PRIMARY",
"key_len": "5",
"ref": "const,const",
"rows": 693,
"filtered": 100,
"Extra": "Using where; Using filesort"
}
]
}

Using filesort表示为内存排序,而没有使用到索引。因为联合索引都是一个一个分离的B+树索引。比方说联合索引 (col1, col2,col3),我知道在逻辑上是先按照col1进行排序再按照col2进行排序最后再按照col3进行排序。引文使用了两个字段排序,虽然排序顺序一样,但是因为第一个字段是个范围值,MySQL需要聚合到所有数据在内存排序,也就是能保证times是顺序的,但是又要按照uid排序需要组合后在排序。同理能看出如果是排序是按照最左原则,在最后一个字段排序,且只是用一个字段排序是有效的,且不能夸字段

1
2
3
4
5
select * from table where col1 < xx order by col可以索引使用排序。
select * from table where col1 < xx order by col2 不可以使用索引排序。
但是前边是定值的是可以排序:【MySQL在存储的按照col1进行排序再按照col2进行排序最后再按照col3进行排序】
select * from table where col1 == xx order by col2 可以使用索引排序。
select * from table where col1 == xx order by col2,clo3 不可以使用索引排序【需要组合col2,clo3数据后排序】。