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;
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | rental | null | ref | rental_date | rental_date | 6 | const | 1 | 100 | Using index condition; Using filesort |
通過explain知道程腹,查詢命中索引rental_date匣吊,但是同時使用到 filesort。雖然命中了索引寸潦,但是在查詢的總損耗中色鸳,排序造成了額外的性能消耗。
那么见转,如果使用索引掃描代替排序的過命雀,我們可以先看下排序時命中索引的規(guī)則。
索引的列的順序和ORDER BY子句的順序完全一致斩箫,并且所有列的排序方向(倒序或正序)完全一致時吏砂,MYSQL采用索引對結果進行排序。
根據(jù)上面的規(guī)則乘客,從新梳理查詢sql狐血,如果想我的排序sql命中rental_date索引,那么我的sql應該是這樣易核。
explain select *
from rental
where rental_date = '2020-05-25'
order by rental_date,inventory_id,customer_id;
執(zhí)行結果
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | rental | ref | rental_date | rental_date | 6 | const | 1 | 100 | Using index condition |
可以看到匈织,此時執(zhí)行,沒有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;
執(zhí)行結果與上面相同
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | rental | ref | rental_date | rental_date | 6 | const | 1 | 100 | Using index condition |
那么返回到第一條sql,如果sql不變厌蔽,想讓他走索引掃描代替排序操作牵辣,需要怎么做呢
CREATE INDEX rental_date_invent on rental(rental_date,inventory_id);