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

2021-08-15 01:21:33 字數 2966 閱讀 4508

今天看了《高效能mysql》的索引掃瞄做排序章節,並且親身實踐了一下,發現有些結果與原書不一樣,個人猜測是mysql版本不一樣造成的,下面分享一下我個人的筆記。

mysql 有兩種方式生成有序結果:通過排序操作或者按索引順序掃瞄。

如果explain出來type列的值為index,則說明mysql使用索引掃瞄來做排序。(這句有疑問,很多情況下都type都不是index,卻可以進行索引排序)

掃瞄索引本身是很快的,因為只需從一條索引記錄移動到緊接著的下一條記錄。但如果索引不能覆蓋查詢所需的全部列,那就不得不每掃瞄一條索引記錄就都回表查詢一次對應的行。這基本上都是隨機i/o(有關io我找到一篇描述生動的文章:理解i/o:隨機和順序),因此按索引順序讀取的速度通常要比順序地全表掃瞄慢,尤其是在i/o密集型的工作負載時。

mysql可以同時使用同乙個索引既滿足查詢,又滿足排序。因此,如果可能,設計索引是應該盡可能

地同時滿足這兩個任務,這樣是最好的。

只有當索引的列順序和order by子句的順序完全一致時,並且所有列的排序方向(倒序或正序)都一樣時,

mysql才能使用索引來對結果排序。如果需要關聯表來查詢,則只有當order by子句引用的字段全部為第乙個表時,才會使用索引做排序。

order by子句和查詢型查詢限制是一樣的,需要滿足索引的最左字首的要求,否則mysql都需要執行排序操作,而無法利用索引排序。

不過有一種情況是order by子句可以不滿足索引的最左字首要求,就是前導列為常量的時候,如果where子句或者join子句中對這些列指定了常量,就可以彌補索引的不足(下面會有例子)

下面的例子都會以例項資料庫sakila(mysql安裝成功後自帶的乙個示例資料庫)的rental表作為演示,其中表上有

rental_date  (rental_date,inventory_id,customer_id)這個多列索引,我們從下面一例中explain中可以看出extra裡並沒有出現檔案排序(filesort)操作(

using filesort(mysql中無法利用索引完成的排序操作稱為「檔案排序」)當我們試圖對乙個沒有索引的字段進行排序時,就是filesoft。它跟檔案沒有任何關係,實際上是內部的乙個快速排序。

):

-- 即使order by子句不滿足最左字首要求,也可用於查詢排序,因為第一列被指定為乙個常數

explain select rental_id, staff_id from rental

where rental_date = '2005-05-25'

order by inventory_id, customer_id;

-- 第一列提供常量條件,使用第二列進行排序,這兩列組合在一起,形成索引最左字首,所以可以索引排序,沒有出現filesort

explain select rental_id, staff_id from rental

where rental_date = '2005-05-25'

order by inventory_id desc;

-- 原書:這個也沒問題,因為order by使用的兩列就是索引的最左字首 

-- 我個人實踐:我這裡試過是不行的,難道是mysql的改良捨棄掉了某種演算法?

explain select rental_id, staff_id from rental

where rental_date > '2005-05-25'

order by rental_date, inventory_id;

-- 原書:這個查詢使用了兩種不同的排序方向,不能進行索引排序 

-- 我個人實踐:我試過是可以的,可能mysql改良了吧

explain select rental_id, staff_id from rental

where rental_date = '2005-05-25'

order by rental_date desc, inventory_id asc;

-- where 和 order by 的列無法組成索引最做字首 

explain select rental_id, staff_id from rental

where rental_date = '2005-05-25'

order by customer_id;

-- 索引列在第一列上是範圍條件,因此mysql無法使用索引的其餘列 

explain select rental_id, staff_id from rental

where rental_date > '2005-05-25'

order by inventory_id, customer_id;

-- inventory_id上有多個條件,對於排序萊說,這也屬於範圍查詢

explain select rental_id, staff_id from rental

where rental_date = '2005-05-25' and inventory_id in(1,2)

order by customer_id;

/*

理論上是可以用索引進行關聯排序的,但由於優化器在優化時把film_actor表當作關聯的第二張表,

因此實際上無法使用索引

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

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

MySQL 使用索引掃瞄來做排序

mysql有兩種方式可以生成有序的結果 通過排序操作 或者按照索引順序掃瞄 如果explain 出來的結果的type列的值為 index 則說明mysql使用了索引掃瞄來做排序 不要和extra列的 using index 搞混 掃瞄索引本身是很快的,因為只需要從一條索引記錄移動到緊接著的下一條記錄...

mysql優化之索引掃瞄排序

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