描述
sql的優化主要是圍繞着在查詢語句的時候盡量使用索引避免全表掃描。
使用索引
- 對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
避免判斷null值
- 應盡量避免在 where 子句中對字段進行 null 值判斷(is null,is not null),否則將導致引擎放棄使用索引而進行全表掃描。
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
避免不等值判斷
- 應盡量避免在 where 子句中使用!=或<>操作符,否則引擎將放棄使用索引而進行全表掃描。
MySQL只對以下操作符才使用索引:
<, <= ,= ,> ,>= ,between,in,以及某些時候的like(不以通配符%或_開頭的情形)
避免使用or邏輯
- 應盡量避免在 where 子句中使用 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
慎用in和not in邏輯
- in 和 not in 也要慎用,否則會導致全表掃描,
如:
select id from t1 where num in(select id from t2 where id > 10)
此時外層查詢會全表掃描,不使用索引。
可以修改為:
select id from t1,(select id from t1 where id > 10) t2 where t1.id = t2.id
此時索引被使用,可以明顯提升查詢效率。
注意模糊查詢
like以通配符開頭,也會導致索引失效。
下面的查詢也將導致全表掃描:
select id from t where name like '%abc%'
模糊查詢如果是必要條件時,
可以使用select id from t where name like 'abc%' 來實現模糊查詢,此時索引將被使用。
如果頭匹配是必要邏輯,建議使用全文搜索引擎(Elastic search、Lucene、Solr等)。
通過組合索引可以解決like '%字符串%'索引失效的問題
可以在查詢的字段上創建組合索引,假設以name,age字段建索引
但是如果查詢sql中存在name,age之外的字段,索引將會失效,進行全表掃描。
使用短索引:
CREATE INDEX index_name ON table_name (column(length))
例如,如果有一個CHAR(255)的列,如果在前10個或20個字符內,多數值是惟一的,那么就不要對整個列進行索引,短索引不僅可以提高查詢速度而且可以節省磁盤空間和I/O操作。
盡量不要包含多個列的排序,盡量使用默認排序
因為:MySQL查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那么order by中的列是不會使用索引的
不要在列上進行運算
如果在列上進行計算將導致每個行都會進行運算,這將導致索引失效而進行全表掃描,
select * from users where YEAR(adddate)<2007可以修改為:select * from users where adddate<’2007-01-01′
最佳左前綴法則
在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓字段順序與索引順序相一致。
注意
建議:一個表的索引數最好不要超過6個
用 exists 代替 in
很多時候用 exists 代替 in 是一個好的選擇:
有一個口訣:外層查詢表小於子查詢表,則用exists,外層查詢表大於子查詢表,則用in,如果外層和子查詢表差不多,則愛用哪個用哪個。
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists (select 1 from b where num=a.num)
其中:select num from a 的結果就是外層查詢表,(select 1 from b where num=a.num)的結果是子查詢表
參考:in和exist的使用
表格字段類型選擇
盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。
盡可能的使用 varchar 代替 char ,因為首先可變長度字段存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。
查詢語法中的字段
任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段
索引無關優化
-
不使用*、盡量不使用union,union all等關鍵字、盡量不使用or關鍵字、盡量使用等值判斷。
-
表連接建議不超過5個。如果超過5個,則考慮表格的設計。(互聯網應用中)
-
表連接方式使用外聯優於內聯
-
大數據量級的表格做分頁查詢時,如果頁碼數量過大,則使用子查詢配合完成分頁邏輯。
Select * from table limit 1000000, 10
Select * from table where id in (select pk from table limit 100000, 10)