SQL優化常用的幾種方法


為什么要對SQL優化:

1、執行性能低
2、等待時間過長
3、SQL寫的太差
4、索引失效
·····等等

SQL優化的一些方法:

1、EXPLAIN

做MySQL優化,我們要善用EXPLAIN查看SQL執行計划。

下面來個簡單的示例,標注(1、2、3、4、5)我們要重點關注的數據:

type列,連接類型。一個好的SQL語句至少要達到range級別。杜絕出現all級別。

key列,使用到的索引名。如果沒有選擇索引,值是NULL。

key_len列,索引長度。不損失精確性的情況下,長度越短越好

rows列,掃描行數。該值是個預估值。

extra列,詳細說明。注意,常見的不太友好的值,如下:Using filesort,Using temporary。

注:MySQL Explain詳解可以參考 https://www.cnblogs.com/leeego-123/p/11846613.html

2、區分in和exists

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

用下面的語句替換:

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

區分in和exists主要是造成了驅動順序的改變(這是性能變化的關鍵)。

如果是exists,那么以外層表為驅動表,先被訪問;

如果是IN,那么先執行子查詢。

所以IN適合於外表大而內表小的情況;EXISTS適合於外表小而內表大的情況。

3、避免在where子句中對字段進行null值判斷

對於null的判斷會導致引擎放棄使用索引而進行全表掃描。

可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:

select id from t where num=0

4、in 和 not in 也要慎用,否則會導致全表掃描

如:

select id from t where num in(1,2,3)

對於連續的數值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3

5、避免在where子句中對字段進行表達式操作

比如下面的SQL中對字段就行了算術運算,這會造成引擎放棄使用索引,

select user_id,user_project from user_base where age*2=36;

建議改成:

select user_id,user_project from user_base where age=36/2;

再比如

select id from t where num/2=100

應改為:

select id from t where num=100*2

6、應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描

7、應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描

select id from t where substring(name,1,3)='abc'; --name以abc開頭的id

應改為:

select id from t where name like 'abc%'

8、避免隱式類型轉換

隱式轉換導致索引失效.這一點應當引起重視.也是開發中經常會犯的錯誤.

由於表的字段tu_mdn定義為varchar2(20),但在查詢時把該字段作為number類型以where條件傳給Oracle,這樣會導致索引失效.

錯誤的例子:

select * from test where tu_mdn=13333333333;

正確的例子:

select * from test where tu_mdn='13333333333';

9、對於聯合索引(組合索引)來說,要遵守最左前綴法則

可以參考這兩篇博客——

https://w.cnblogs.com/rocker-pg/p/11635414.html

https://www.cnblogs.com/hongmoshui/p/10429842.html

10、任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。    

SELECT*增加很多不必要的消耗(CPU、IO、內存、網絡帶寬);

增加了使用覆蓋索引的可能性;

當表結構發生改變時,前斷也需要更新。

所以要求直接在select后面接上字段名。

11、如果排序字段沒有用到索引,就盡量少排序

12、如果限制條件中其他字段沒有索引,盡量少用or

or兩邊的字段中,如果有一個不是索引字段,而其他條件也不是索引字段,會造成該查詢不走索引的情況。

很多時候使用union all或者是union(必要的時候)的方式來代替“or”會得到更好的效果。

select id from t where num=10 or num=20

可以這樣查詢:

select id from t where num=10
union all
select id from t where num=20

13、盡量用union all代替union

union和union all的差異主要是前者需要將結果集合並后再進行唯一性過濾操作,這就會涉及到排序,增加大量的CPU運算,加大資源消耗及延遲。

當然,union all的前提條件是兩個結果集沒有重復數據。

14、不建議使用%前綴模糊查詢

例如LIKE“%name”或者LIKE“%name%”,這種查詢會導致索引失效而進行全表掃描。但是可以使用LIKE “name%”。

假如有這樣一列code的值為'AAA','AAB','BAA','BAB' ,如果where code like '%AB'條件

由於前面是模糊的,所以不能利用索引的順序,必須一個個去找,看是否滿足條件。這樣會導致全索引掃描或者全表掃描。

如果是這樣的條件where code like 'A % ',就可以查找CODE中A開頭的CODE的位置,

當碰到B開頭的數據時,就可以停止查找了,因為后面的數據一定不滿足要求。這樣就可以利用索引了。

15、索引數量不要過多

索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,

因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。

一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM