天天看點

談談SQL優化

##一.索引失效的情況

1.如果條件中有or,即使其中有條件帶索引也不會使用(or條件均建獨立索引,用UNION替換or)

2.對于多列索引,不是使用的第一部分,則不會使用索引

3.like查詢是以%開頭(以%結尾是可以的)

4.如果列類型是字元串,那一定要在條件中将資料使用引号引用起來,否則不使用索引

5.如果mysql估計使用全表掃描要比使用索引快,則不使用索引

6.應盡量避免在 where 子句中對字段進行 null 值判斷,否則将導緻引擎放棄使用索引而進行全表掃描,如

select id from t where num is null      

(最好不要給資料庫留NULL,盡可能的使用 NOT NULL填充資料庫.)

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

8.in 和 not in 也要慎用,否則會導緻全表掃描(對于連續的數值,能用 between 就不要用 in 了)(用 exists 代替 in)

select num from a where exists(select 1 from b where num=a.num)      

9.如果在 where 子句中使用參數,也會導緻全表掃描。因為SQL隻有在運作時才會解析局部變量,但優化程式不能将通路計劃的選擇推遲到運作時;它必須在編譯時進行選擇。然 而,如果在編譯時建立通路計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句将進行全表掃描:

select id from t where num = @num      

可以改為強制查詢使用索引:

select id from t with(index(索引名)) where num = @num      

10.應盡量避免在 where 子句中對字段進行表達式操作,這将導緻引擎放棄使用索引而進行全表掃描。如:

select id from t where num/2 = 100      

應改為

select id from t where num = 100*2      

11.應盡量避免在where子句中對字段進行函數操作,這将導緻引擎放棄使用索引而進行全表掃描。如

select id from t where substring(name,1,3) = ’abc’       -–name以abc開頭的id
select id from t where datediff(day,createdate,’2005-11-30′) = 0    -–‘2005-11-30’    --生成的id      

應改為

select id from t where name like 'abc%'
select id from t where createdate >= '2005-11-30' and createdate < '2005-12-1'      

12.在使用索引字段作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引将不會被使用,并且應盡可能的讓字段順序與索引順序相一緻。

##其他優化

1.盡量使用數字型字段,若隻含數值資訊的字段盡量不要設計為字元型,這會降低查詢和連接配接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連 接時會逐個比較字元串中每一個字元,而對于數字型而言隻需要比較一次就夠了。

2.盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節省存儲空間,其次對于查詢來說,在一個相對較小的字段内搜尋效率顯然要高些。

3.任何地方都不要使用 select * from t ,用具體的字段清單代替“*”,不要傳回用不到的任何字段。

4.盡量避免使用遊标,因為遊标的效率較差

5.拆分大的 DELETE 或INSERT 語句,批量送出SQL語句

while(1){

   //每次隻做1000條

   mysql_query(“delete from logs where log_date <= ’2012-11-01’ limit 1000”);

   if(mysql_affected_rows() == 0){

     //删除完成,退出!
     break;
  }

//每次暫停一段時間,釋放表讓其他程序/線程通路。
usleep(50000)

}      

參考文章:

繼續閱讀