MySQL語句優化常見誤區和優化技巧

MySQL語句優化常見誤區與優化技巧

 

原文鏈接:http://www.2cto.com/database/201303/195666.html

1  常見誤區

誤區1:count(1)和count(primary_key)優於count(*)

誤區2:count(*)和count(column)是一樣的

count(*)表示整個結果集有多少記錄

count(column)表示結果集中有多少個column字段不爲空的記錄

誤區3:select a,b from …比select a,b,c from …可以讓數據庫訪問更少的數據量

大多數關係型數據庫都是按照行方式存儲,而數據存取操作都是以一個固定大小的IO單元爲單位,大多數時候每個IO單元存儲了多少行,每行都是存儲了該行的所有字段(lob等特殊類型字段除外)。例外情況是我們的這個查詢在索引中就可以完成,也就是當只取a,b兩個字段的時候不需要回表,而c這個字段不在使用的索引中,需要回表取得數據,二者的IO量會有較大差異(覆蓋索引)。

誤區4:order by 一定要做排序操作

索引數據時有序的,如果所需要的數據和某個索引順序一致,而且查詢又通過該索引執行,那麼數據庫一般會省略排序操作。

誤區5:執行計劃中有filesort就會進行磁盤文件排序

 

2  語句優化技巧

1)儘量少join

2)儘量少排序

減少排序的方法:

l  通過利用索引來排序

l  減少參與排序的記錄條數

l  非必要不對數據進行排序

l  ……

3)儘量避免select *

當查詢結果僅僅只需要在索引中就能找到的時候,會極大減少IO量的。

4)儘量用join代替子查詢

MySQL的子查詢執行計劃一直存在較大問題

5)儘量少or

6)儘量用union all代替union

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

7)儘量早過濾

8)避免類型轉換

本處所述的類型轉換是指where子句中出現column字段的類型和傳入的參數類型不一致的時候發生的類型轉換。人爲進行此種類型轉換,直接導致MySQL無法使用索引。

9)優先優化高併發的SQL,而不是執行頻率低某些“大”SQL

10)從全局出發,而不是片面調整

儘可能對每一條運行在數據庫中的SQL進行explain

 

原文鏈接:http://blog.sina.com.cn/s/blog_95ee143401013gzf.html

11)避免使用不兼容的數據類型

儘量減少對數據庫的訪問次數

儘量減少對錶的訪問行數,最小化結果集,從而減輕網絡負擔

在數據窗口使用SQL時,儘量把使用的索引放在選擇的首列

12)索引字段上進行運算會使索引失效

儘量避免在where子句中對字段進行函數或表達式操作

SELECT * FROM T1 WHERE F1/2=100應改爲

SELECT * FROM T1 WHERE F1=100*2

13)避免使用!=或<>、IS NULL或IS NOT NULL、IN、NOT IN等這樣的操作符

14)儘量使用數字型字段

15)合理使用EXISTS、NOT EXISTS子句

1、SELECT SUM(T1,C1) FROM T1 WHERE (SELECT COUNT(*) FROM T2 WHERET2.C2=T1.C2>0)

2、SELECT SUM(T1,C1) FROM T1 WHERE EXISTS(SELECT * FROM T2 WHERET2.C2=T1.C2)

兩者產生相同的結果,但是後者的效率顯然高於前者,因爲後者不會產生大量鎖定的表掃描或是索引掃描。如果想校驗表裏是否存在某條記錄,不要用count(*),可以用EXISTS代替。

16)能夠用BETWEEN的就不用IN

17)能夠用DISTINCT的就不用GROUP BY

18)儘量不要用SELECT INTO語句,SELECT INTO語句會導致表鎖定,阻止其他用戶訪問該表

19)必要時強制查詢優化器使用某個索引

SELECT * FROM T1 WHERE nextprocess=1 AND processidIN (8,32,45)改成

SELECT * FROM T1 (INDEX = IX_ProcessID)WHERE nextprocess =1 AND processid IN (8,32,45)

則查詢優化器將會強行利用索引IX_ProcessID執行查詢

20)消除對大型錶行數據的順序存取

21)儘量避免在索引過的字符數據中,使用非打頭字母搜索。這也使得引擎無法利用索引

SELECT * FROM T1 WHERE NAME LIKE ‘%L%’

SELECT * FROM T1 WHERE SUBSTRING(NAME,2,1)=’L’

SELECT * FROM T1 WHERE NAME LIKE ‘L%’

即使NAME字段建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有數據逐條操作來完成任務,而第三個查詢能夠使用索引來加快操作,不要習慣性的使用’%L%’這種方式(會導致全表掃描),如果可以使用’L%’相對來說更好

22)關於update語句的建議

l  儘量不要修改主鍵字段

l  當修改varchar型字段時,儘量使用相同長度內容的值代替

l  儘量最小化對於含有update觸發器的表的update操作

l  避免update將要複製到其他數據庫的列

l  避免update建有很多索引的列

l  避免update在where子句條件中的列

23)程序中如果一次性對同一個表插入多條數據時,可以將其拼成一條語句執行效率會更高

insert into student(sid,sname) values (11,’zhangsan’);

insert into student(sid,sname) values (12,’lisi’);

insert into student(sid,sname) values (13,’liqin’);

 

insert into student(sid,sname) values (11,’zhangsan’),(12,’lisi’),(13,’liqin’);

 

24)不要在選擇的欄位上放置索引,應該在條件選擇的語句上合理的放置索引

SELECT id,title,content,cat_id FROM articleWHERE cat_id=1;

上面這個語句,在id/title/content上放置索引是毫無意義的,對這個語句沒有任何優化作用,但是如果在外鍵cat_id上放置一個索引,作用就相當大。

 

轉載請註明出處:MySQL語句優化常見誤區與優化技巧

發佈了40 篇原創文章 · 獲贊 52 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章