一、小表驅動大表
簡單理解就是外層循環的次數小於內存循環的次數。
小表驅動大表,即小的數據集驅動大的數據集。
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