mysql排序的骚操作-索引扫描

本文探讨了MySQL InnoDB引擎中B+树索引的特性和使用,通过示例解释如何利用索引来避免排序操作带来的性能损耗。通过调整SQL查询,使得查询能够利用索引扫描而非文件排序,从而提高查询效率。此外,还介绍了索引命中规则,即索引列顺序与ORDER BY子句一致且方向相同时,MySQL将直接使用索引进行排序。
摘要由CSDN通过智能技术生成

mysql 的InnoDB引擎,使用的B+树索引结构,天生的就是有序的;由于这个特性,可以通过合理的使用索引,来避免额外排序操作带来的损耗。下面举例说明

create table rental
(
    rental_id    bigint   default 0 comment 'id',
    rental_date  datetime default now() comment '租赁日期',
    inventory_id bigint   default 0 comment '商品ID',
    customer_id  bigint   default 0 comment '顾客ID',
    staff_id     bigint   default 0 comment '员工ID',
    PRIMARY KEY (rental_id),
    unique key rental_date (rental_date, inventory_id, customer_id),
    key idx_fk_inventory_id (inventory_id),
    key idx_fk_customer_id (customer_id),
    key idx_fk_staff_id (staff_id)
);

我先来查询下5.25 进行租赁记录按照商品id排序

explain select *
from rental
where rental_date = '2020-05-25'
order by inventory_id;
idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLErentalnullrefrental_daterental_date6const1100Using index condition; Using filesort

通过explain知道,查询命中索引rental_date,但是同时使用到 filesort。虽然命中了索引,但是在查询的总损耗中,排序造成了额外的性能消耗。
那么,如果使用索引扫描代替排序的过,我们可以先看下排序时命中索引的规则。

索引的列的顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向(倒序或正序)完全一致时,MYSQL采用索引对结果进行排序。

根据上面的规则,从新梳理查询sql,如果想我的排序sql命中rental_date索引,那么我的sql应该是这样。

explain select *
from rental
where rental_date = '2020-05-25'
order by rental_date,inventory_id,customer_id;

执行结果

idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLErentalrefrental_daterental_date6const1100Using index condition

可以看到,此时执行,没有using filesort。也就是使用索引扫描代替了结果排序的动作。

有一个点需要注意,当前导列为常量时,order by 子句不满足最左匹配原则,仍然可以命中索引。仍然以 rental_date (rental_date, inventory_id, customer_id)索引为例。也就是把列rental_date前置为条件的前提下,order by 最左边不是rental_date,也可以认为rental_date在,会命中索引。

explain select *
from rental
where rental_date = '2005-05-25'
order by inventory_id,customer_id;

执行结果与上面相同

idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLErentalrefrental_daterental_date6const1100Using index condition

那么返回到第一条sql,如果sql不变,想让他走索引扫描代替排序操作,需要怎么做呢

CREATE INDEX rental_date_invent on rental(rental_date,inventory_id);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值