談談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)

}

參考文章:http://www.cnblogs.com/yunfeifei/p/3850440.html

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