mysql優化之索引掃瞄排序

2021-10-11 22:48:29 字數 4135 閱讀 4913

前言:

mysql有兩種方式可以生成有序的結果:通過排序操作或者按索引順序掃瞄,如果explain出來的type列的值為index,則說明mysql使用了索引掃瞄來做排序。

掃瞄索引本身是很快的,因為只需要從一條索引記錄移動到緊接著的下一條記錄。但如果索引不能覆蓋查詢所需的全部列,那麼就不得不每掃瞄一條索引記錄就得回表查詢一次對應的行,這基本都是隨機io,因此按索引順序讀取資料的速度通常要比順序地全表掃瞄慢。

mysql可以使用同乙個索引即滿足排序,又用於查詢行,如果可能的話,設計索引時應該盡可能地同時滿足這兩種任務。

只有當索引的列順序和order by子句的順序完全一致,並且所有列的排序方式都一樣時,mysql才能夠使用索引來對結果進行排序,如果查詢需要關聯多張表,則只有當order by子句引用的字段全部為第一張表時,才能使用索引做排序。order by子句和查詢型查詢的限制是一樣的,需要滿足索引的最左字首的要求,否則,mysql都需要執行順序操作,而無法利用索引排序。

# 使用索引掃瞄來做排序

​        mysql有兩種方式可以生成有序的結果:通過排序操作或者按索引順序掃瞄,如果explain出來的type列的值為index,則說明mysql使用了索引掃瞄來做排序

​        掃瞄索引本身是很快的,因為只需要從一條索引記錄移動到緊接著的下一條記錄。但如果索引不能覆蓋查詢所需的全部列,那麼就不得不每掃瞄一條索引記錄就得回表查詢一次對應的行,這基本都是隨機io,因此按索引順序讀取資料的速度通常要比順序地全表掃瞄慢

​        mysql可以使用同乙個索引即滿足排序,又用於查詢行,如果可能的話,設計索引時應該盡可能地同時滿足這兩種任務。

​        只有當索引的列順序和order by子句的順序完全一致,並且所有列的排序方式都一樣時,mysql才能夠使用索引來對結果進行排序,如果查詢需要關聯多張表,則只有當orderby子句引用的字段全部為第一張表時,才能使用索引做排序。order by子句和查詢型查詢的限制是一樣的,需要滿足索引的最左字首的要求,否則,mysql都需要執行順序操作,而無法利用索引排序

sql--注意,這是mysql5.7執行的結果,mysql8執行有些地方會不同,理解下意思就行,資料庫是mysql官網上的sakila

sakila資料庫中rental表在rental_date,inventory_id,customer_id上有rental_date的索引(rental_date為組合索引,包括rental_date,inventory_id,customer_id)

1、使用rental_date索引為下面的查詢做排序

explain select rental_id,staff_id from rental where rental_date='2005-05-25' order by inventory_id,customer_id\g

*************************** 1. row ***************************

id: 1

select_type: ******

table: rental

partitions: null

type: ref

possible_keys: rental_date

key: rental_date

key_len: 5

ref: const

rows: 1

filtered: 100.00

extra: using index condition

1 row in set, 1 warning (0.00 sec)

order by子句不滿足索引的最左字首的要求,也可以用於查詢排序,這是因為所以你的第一列(rental_date='2005-05-25')被指定為乙個常數

2、該查詢為索引的第一列提供了常量條件,而使用第二列進行排序,將兩個列組合在一起,就形成了索引的最左字首

explain select rental_id,staff_id from rental where rental_date='2005-05-25' order by inventory_id desc\g

*************************** 1. row ***************************

id: 1

select_type: ******

table: rental

partitions: null

type: ref

possible_keys: rental_date

key: rental_date

key_len: 5

ref: const

rows: 1

filtered: 100.00

extra: using where

1 row in set, 1 warning (0.00 sec)

3、下面的查詢不會利用索引(第一列使用了範圍查詢)

explain select rental_id,staff_id from rental where rental_date>'2005-05-25' order by rental_date,inventory_id\g

*************************** 1. row ***************************

id: 1

select_type: ******

table: rental

partitions: null

type: all

possible_keys: rental_date

key: null

key_len: null

ref: null

rows: 16005

filtered: 50.00

extra: using where; using filesort

4、該查詢使用了兩中不同的排序方向,但是索引列都是正序排序的

explain select rental_id,staff_id from rental where rental_date>'2005-05-25' order by inventory_id desc,customer_id asc\g

*************************** 1. row ***************************

id: 1

select_type: ******

table: rental

partitions: null

type: all

possible_keys: rental_date

key: null

key_len: null

ref: null

rows: 16005

filtered: 50.00

extra: using where; using filesort

1 row in set, 1 warning (0.00 sec)

5、該查詢中引用了乙個不再索引中的列

explain select rental_id,staff_id from rental where rental_date>'2005-05-25' order by inventory_id,staff_id\g

*************************** 1. row ***************************

id: 1

select_type: ******

table: rental

partitions: null

type: all

possible_keys: rental_date

key: null

key_len: null

ref: null

rows: 16005

filtered: 50.00

extra: using where; using filesort

1 row in set, 1 warning (0.00 sec)

使用索引掃瞄來做排序 mysql索引優化

mysql有兩種方式可以生成有序的結果 通過排序操作或者按索引順序掃瞄,如果explain出來的type列的值為index,則說明mysql使用了索引掃瞄來做排序 掃瞄索引本身是很快的,因為只需要從一條索引記錄移動到緊接著的下一條記錄。但如果索引不能覆蓋查詢所需的全部列,那麼就不得不每掃瞄一條索引記...

Mysql索引掃瞄排序

mysql有兩種操作可以用來生成有序結果 排序操作 將查詢出來的結果使用排序演算法進行排序 按索引順序掃瞄 order by語句後跟著乙個被索引的列,如此一來索引的順序就是索引對應記錄的順序,這樣直接順著索引一直往下讀取記錄即可得到有序的結果。按照索引順序掃瞄的好處是不言而喻的,因為查詢出來的結果就...

mysql索引 之使用索引掃瞄做排序

今天看了 高效能mysql 的索引掃瞄做排序章節,並且親身實踐了一下,發現有些結果與原書不一樣,個人猜測是mysql版本不一樣造成的,下面分享一下我個人的筆記。mysql 有兩種方式生成有序結果 通過排序操作或者按索引順序掃瞄。如果explain出來type列的值為index,則說明mysql使用索...