SQL語句編寫注意事項


1、SQL編寫注意事項

1.1 null 列

  null 列使用索引是無意義的,任何包含null 值的列都不會包含在索引中。因此where 語句中的is null 或者 is not null 的語句,導致索引失效。

1.2 concat 或 ||

  concate 或 || 是mysql 和 oracle 的字符串連接操作,如果對列進行函數操作,就會忽略索引的使用,比如下面的查詢語句:

  

-- 忽律索引
select ... from .. where first_name || '' || last_name = 'bill gates' ;
-- 使用索引
select ... from .. where first_name = 'bill' and last_name = 'bill gates' ;

1.3 like 

  使用like進行模糊查詢時,如果通配符%在首位則索引會失效,如下sql語句:

 

-- 無法使用索引
select .. from .. where name like'%t%'
-- 可以使用索引
select .. from .. where name like 't%' ;

1.4 order by

  order by 子句中不要使用非索引列或嵌套表達式,這樣都會導致性能降低。

1.5 使用 !=或<> 操作會使索引失效

-- 索引無效
select .. from .. where sal != 3000 ;
select .. from .. where sal <>3000 ;

1.6  使用 or 需要注意

1、or兩邊的字段中,如果有一個不是索引字段,而其他條件也不是索引字段,會造成該查詢不走索引的情況。很多時候使用union all或者是union(必要的時候)的方式來代替“or”會得到更好的效果。

2、如果or 兩邊字段都有索引,用explain 也可能出現索引失效的情況

對於使用or導致索引失效的情況
select id
from t where c1=1 or c2=2 改為 select id from t where c1=1 UNION ALL select id from t where c2=2

1.7 where 和 having

  select .. from .. on .. where .. group by .. having .. order by .. limit ..,以上是sql語句的語法結構,其中on、where和having是有過濾行為的,過濾行為越能提前完成就越可以減少傳遞給下一個階段的數據量,因此如果在having中的過濾行為能夠在where中完成,則應該優先考慮where來實現。

1.8 exists 和 in 的選擇

  

select * from 表A where id in (select id from 表B)
相當於
select * from 表A where id exits(select id from 表B where 表B.id =表A.id)

在選擇使用exits 和 in 的原則根據驅動順序的進行選擇,如果是exists,那么以外層表為驅動表,先被訪問,如果是IN,那么先執行子查詢。所以

1、當A表數據量大,B表數據量小情況下使用IN

2、當B表數據量大,A表數據量小使用exitsts

關於not in和not exists,推薦使用not exists,不僅僅是效率問題,not in可能存在邏輯問題。如何高效的寫出一個替代not exists的SQL語句?

select colname … from A表 where a.id not in (select b.id from B表)
修改為:
select  colname … from A表 left join B 表 where a.id=b.id and b.id is null

1.9 where 后面的‘=‘后面使用函數、算術運算或其他表達式運算,系統將可能無法正確使用索引

select id from t where num/2=100
可以更改為
select id from t where num=100*2 (該方法索引不失效)

select id from t where substring(name,1,3)='abc'
可以更改

select id from t where name like "abc%"

1.10 避免對where 后面的字段進行隱私類型轉換

where子句中出現column字段的類型和傳入的參數類型不一致的時候發生的類型轉換,建議先確定where中的參數類型。

select name from t where int(age)=20 對字段進行了類型轉換,索引失效

 1.11 對於聯合索引注意最左法則

  舉列來說索引含有字段id、name、school,可以直接用id字段,也可以id、name這樣的順序,但是name;school都無法使用這個索引。所以在創建聯合索引的時候一定要注意索引字段順序,常用的查詢字段放在最前面。

1.12  注意范圍查詢 between > <

     使用范圍查詢會使范圍查詢后面的索引失效

1.13 對於join的優化

  

  LEFT JOIN A表為驅動表,INNER JOIN MySQL會自動找出那個數據少的表作用驅動表,RIGHT JOIN B表為驅動表。

  1)mysql 每有fulljoin

  

select * from A left join B on B.name = A.name where B.name is null union allselect * from B;

  2)盡量使用inner join,避免left join:

  參與聯合查詢的表至少為2張表,一般都存在大小之分。如果連接方式是inner join,在沒有其他過濾條件的情況下MySQL會自動選擇小表作為驅動表,但是left join在驅動表的選擇上遵循的是左邊驅動右邊的原則,即left join左邊的表名為驅動表。

  3)合理利用索引:

  被驅動表的索引字段作為on的限制字段。

  4)利用小表去驅動大表:

  

  5)巧用STRAIGHT_JOIN:

  inner join是由MySQL選擇驅動表,但是有些特殊情況需要選擇另個表作為驅動表,比如有group by、order by等「Using filesort」、「Using temporary」時。STRAIGHT_JOIN來強制連接順序,在STRAIGHT_JOIN左邊的表名就是驅動表,右邊則是被驅動表。在使用STRAIGHT_JOIN有個前提條件是該查詢是內連接,也就是inner join。其他鏈接不推薦使用STRAIGHT_JOIN,否則可能造成查詢結果不准確。


免責聲明!

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



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