MySQL索引優化(三)排序索引

一、小表驅動大表

簡單理解就是外層循環的次數小於內存循環的次數。
小表驅動大表,即小的數據集驅動大的數據集。
MySQL中實現表嵌套的方式主要就是in和exists。
下面的A表和B表中的id字段都創建了索引。

1、當B表的數據集小於A表的數據集時,用in優於exists

select * from A where id in (select id from B)

等價於

for select id from B
for select * from A where A.id = B.id

2、當A表的數據集小於B表的數據集時,用exists優於in

select * from A where exists (select 1 from B where B.id = A.id)

等價於

for select * from A
for select * from B where B.id = A.id

因爲exists(subquery)只返回true或者false,因此子查詢中的select *也可以是select 1或者select ‘x’,官方說法是實際執行時會忽略select清單,因此沒有區別。

二、order by關鍵字優化

1、儘量使用Index方式,避免使用FileSort方式排序

創建表

create table tblA (
    age int,
    birth timestamp not null
);

insert into tblA(age, birth) values (22, NOW());
insert into tblA(age, birth) values (23, NOW());
insert into tblA(age, birth) values (24, NOW());

創建索引

create index idx_A_ageBirth on tblA(age, birth);
1)order by能使用索引最左前綴

執行

explain select * from tblA where age > 20 order by age;
explain select * from tblA where age > 20 order by age, birth;

結果如下
在這裏插入圖片描述
可以看到Extra中並沒有Using FileSort。
ps:這種場景也可以,同升或者同降

order by a desc, b desc, c desc
2)如果where使用索引的最左前綴定義爲常量,則order by能使用索引

執行,age = const

explain select * from tblA where age = 20 order by birth, age;

在這裏插入圖片描述
可以看到Extra中並沒有Using FileSort。

3)order by不能使用索引

執行

explain select * from tblA where age > 20 order by birth;
explain select * from tblA where age > 20 order by birth, age;

結果如下
在這裏插入圖片描述
可見Extra都產生了Using fileSort,也就是說當order by後面如果缺少帶頭的索引字段或者字段順序和創建的索引字段不一致,就會導致Using FileSort。
order by滿足兩情況,會使用Index方式排序

  • order by語句使用索引最左前列
  • 使用where子句與order by子句條件列組合滿足索引最左前列

總結一句話:儘可能在索引列上完成排序操作(使用被創建索引的字段進行排序),遵循索引創建的最佳左前綴。

2、如果不在索引列上的優化方法

這一塊問題比較複雜,就不寫了。

1)雙路排序
2)單路排序

嘗試提高sort_buffer_size或者max_lenght_for_sort_data

三、group by關鍵字優化

group by是指是先排序後進行分組,遵循索引創建的最佳左前綴。
where高於having,能寫在where限定的條件就不要去having限定了。
剩下的同order by

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章