在項目中,SQL的調優對項目的性能來說相當重要,全部掌握常見的SQL調優方式是必不可少的,下面介紹幾種常見的SQL的調優方式,供借鑑.數據庫
一.建立索引
1.要儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引
2.(1)在常常須要進行檢索的字段上建立索引,好比要按照表字段username進行檢索,那麼就應該在姓名字段上建立索引,若是常常要按照員工部門和員工崗位級別進行檢索,那麼就應該在員工部門和員工崗位級別這兩個字段上建立索引。
(2)建立索引給檢索帶來的性能提高每每是巨大的,所以在發現檢索速度過慢的時候應該首先想到的就是建立索引。
(3)一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。索引並非越多越好,索引當然能夠提升相應的 select 的效率,但同時也下降了 insert 及 update 的效率,由於 insert 或 update 時有可能會重建索引,因此怎樣建索引須要慎重考慮,視具體狀況而定。網絡
二.避免在索引上使用計算
在where字句中,若是索引列是計算或者函數的一部分,DBMS的優化器將不會使用索引而使用全表查詢,函數
屬於計算的一種,同時在in和exists中一般狀況下使用EXISTS,由於in不走索引
效率低:併發
select * from user where salary*22>11000(salary是索引列)
1
效率高:函數
select * from user where salary>11000/22(salary是索引列)
1
三.使用預編譯查詢
程序中一般是根據用戶的輸入來動態執行SQL,這時應該儘可能使用參數化SQL,這樣不只能夠避免SQL注入漏洞
攻擊,最重要數據庫會對這些參數化SQL進行預編譯,這樣第一次執行的時候DBMS會爲這個SQL語句進行查詢優化
而且執行預編譯,這樣之後再執行這個SQL的時候就直接使用預編譯的結果,這樣能夠大大提升執行的速度。性能
四.調整Where字句中的鏈接順序
DBMS通常採用自下而上的順序解析where字句,根據這個原理錶鏈接最好寫在其餘where條件以前,那些能夠
過濾掉最大數量記錄。大數據
五.儘可能將多條SQL語句壓縮到一句SQL中
每次執行SQL的時候都要創建網絡鏈接、進行權限校驗、進行SQL語句的查詢優化、發送執行結果,這個過程
是很是耗時的,所以應該儘可能避免過多的執行SQL語句,可以壓縮到一句SQL執行的語句就不要用多條來執行。優化
六.用where字句替換HAVING字句
避免使用HAVING字句,由於HAVING只會在檢索出全部記錄以後纔對結果集進行過濾,而where則是在聚合前
刷選記錄,若是能經過where字句限制記錄的數目,那就能減小這方面的開銷。HAVING中的條件通常用於聚合函數
的過濾,除此以外,應該將條件寫在where字句中。日誌
七.使用表的別名
當在SQL語句中鏈接多個表時,請使用表的別名並把別名前綴於每一個列名上。這樣就能夠減小解析的時間並減
少哪些友列名歧義引發的語法錯誤。排序
八.用union all替換union
當SQL語句須要union兩個查詢結果集合時,即便檢索結果中不會有重複的記錄,若是使用union這兩個結果集
一樣會嘗試進行合併,而後在輸出最終結果前進行排序,所以若是能夠判斷檢索結果中不會有重複的記錄時候,應
該用union all,這樣效率就會所以獲得提升。索引
九.考慮使用「臨時表」暫存中間結果
簡化SQL語句的重要方法就是採用臨時表暫存中間結果,可是,臨時表的好處遠遠不止這些,將臨時結果暫存在臨時表,後面的查詢就在tempdb中了,這能夠避免程序中屢次掃描主表,也大大減小了程序執行中「共享鎖」阻塞「更新鎖」,減小了阻塞,提升了併發性能。
可是也得避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。
十.只在必要的狀況下才使用事務begin translation
SQL Server中一句SQL語句默認就是一個事務,在該語句執行完成後也是默認commit的。其實,這就是begin tran的一個最小化的形式,比如在每句語句開頭隱含了一個begin tran,結束時隱含了一個commit。
有些狀況下,咱們須要顯式聲明begin tran,好比作「插、刪、改」操做須要同時修改幾個表,要求要麼幾個表都修改爲功,要麼都不成功。begin tran 能夠起到這樣的做用,它能夠把若干SQL語句套在一塊兒執行,最後再一塊兒commit。 好處是保證了數據的一致性,但任何事情都不是天衣無縫的。Begin tran付出的代價是在提交以前,全部SQL語句鎖住的資源都不能釋放,直到commit掉。
可見,若是Begin tran套住的SQL語句太多,那數據庫的性能就糟糕了。在該大事務提交以前,必然會阻塞別的語句,形成block不少。
Begin tran使用的原則是,在保證數據一致性的前提下,begin tran 套住的SQL語句越少越好!有些狀況下能夠採用觸發器同步數據,不必定要用begin tran。
十一.儘可能避免使用遊標
儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。由於遊標的效率較差,若是遊標操做的數據超過1萬行,那麼就應該考慮改寫。
十二.用varchar/nvarchar 代替 char/nchar
儘量的使用 varchar/nvarchar 代替 char/nchar ,由於首先變長字段存儲空間小,能夠節省存儲空間,其次對於查詢來講,在一個相對較小的字段內搜索效率顯然要高些。
不要覺得 NULL 不須要空間,好比:char(100) 型,在字段創建時,空間就固定了, 不論是否插入值(NULL也包含在內),都是佔用 100個字符的空間的,若是是varchar這樣的變長字段, null 不佔用空間。
十三.查詢select語句優化
1.任何地方都不要使用 select * from t ,用具體的字段列表代替「*」,不要返回用不到的任何字段
2.應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描,
如:
select id from t where num is null
1
能夠在num上設置默認值0,確保表中num列沒有null值,
而後這樣查詢:
select id from t where num=0
select id from t where num=10 or num=20
1
2
能夠這樣查詢:
select id from t where num=10
union all
select id from t where num=20
1
2
3
4.不能前置百分
select id from t where name like ‘%abc%’
1
若要提升效率,能夠考慮全文檢索。
select id from t where num in(1,2,3)
1
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
1
6.若是查詢的兩個表大小至關,那麼用in和exists差異不大。
in:
例如:表A(小表),表B(大表)
select * from A where cc in (select cc from B) 效率低,用到了A表上cc列的索引;
select * from A where exists(select cc from B where cc=A.cc) 效率高,用到了B表上cc列的索引。
1
2
相反的
select * from B where cc in (select cc from A) 效率高,用到了B表上cc列的索引;
select * from B where exists(select cc from A where cc=B.cc) 效率低,用到了A表上cc列的索引。
1
2
十四.更新Update語句優化
1.若是隻更改一、2個字段,不要Update所有字段,不然頻繁調用會引發明顯的性能消耗,同時帶來大量日誌
十五. 刪除Delete語句優化語句
1.最高效的刪除重複記錄方法 ( 由於使用了ROWID)例子:
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO); 1 十六.插入Insert語句優化 1.在新建臨時表時,若是一次性插入數據量很大,那麼可使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是數據量不大,爲了緩和系統表的資源,應先create table,而後insert。