1. 程式人生 > >數據庫常用查詢語句寫法(優化)

數據庫常用查詢語句寫法(優化)

服務 創建 and 並且 有效 ever edate truncate exist

常用查詢寫法

Like

like本身效率就比較低,應該盡量避免查詢條件使用like;

原因:

  • 對於like ‘%...%’(全模糊)這樣的條件,是無法使用索引的,全表掃描自然效率很低;
  • 由於匹配算法的關系,模糊查詢的字段長度越大,模糊查詢效率越低。

解決辦法:

  • 盡量避免模糊查詢,如果因為業務需要一定要使用模糊查詢,則至少保證不要使用全模糊查詢,對於右模糊查詢,即like ‘…%’,是會使用索引的;
  • 左模糊like‘%...’無法直接使用索引,但可以利用reverse + function index 的形式,變化成 like ‘…%’;
  • 全模糊是無法優化的,一定要的話考慮用搜索引擎。出於降低數據庫服務器的負載考慮,盡可能地減少數據庫模糊查詢。

NULL

原因:

  • 查詢字段IS NULL時單索引失效,引起全表掃描。

解決方法:

  • SQL語法中使用NULL會有很多麻煩,最好索引列都是NOT NULL的;
  • 對於is null,可以建立組合索引,nvl(字段,0),對表和索引analyse後,is null查詢時可以重新啟用索引查找,但是效率還不是值得肯定;
  • is not null 時永遠不會使用索引。一般數據量大的表不要用is null查詢。

<>、!=

原因:

  • SQL中,不等於操作符會限制索引,引起全表掃描,即使比較的字段上有索引。

解決方法:

  • 通過把不等於操作符改成OR,可以使用索引,避免全表掃描。例如,把column<>’aaa’,改成column<’aaa’ OR column>’aaa’,就可以使用索引了。

OR

原因:

  • where子句中比較的兩個條件,一個有索引,一個沒索引,使用or則會引起全表掃描。例如:where A==1 or B==2,A上有索引,B上沒索引,則比較B=:2時會重新開始全表掃描,可以獲取兩個條件的數據,然後采用union all。

組合索引

  • 排序時應按照組合索引中各列的順序進行排序,即使索引中只有一個列是要排序的,否則排序性能會比較差。【索引中包含排序字段】

Update

  • 如果只更改1、2個字段,不要Update全部字段,否則頻繁調用會引起明顯的性能消耗,同時帶來大量日誌。

多張大數據量

  • 先分頁再JOIN,否則邏輯讀會很高,性能很差。

COUNT函數

  • 不帶任何條件的count會引起全表掃描,並且沒有任何業務意義,是一定要杜絕的。

IN 和 NOT IN

  • 對於連續的數值,用 between:

select id from t where id in(1,2,3)

      => select id from t where id between 1 and 3

  • 用EXISTS代替IN;NOT EXISTS代替NOT IN。

A/B

原因:

  • 不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
  • 引擎放棄使用索引而進行全表掃描

解決方法:

select id from t where id/2 = 10

      => select id from t where id = 2 * 10

SUBSTRING/ DATEDIFF

原因:

  • 不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
  • 引擎放棄使用索引而進行全表掃描。

解決方法:

select id from t where substring(id,1,2) = ‘abcd’

        => select id from t where id like ‘abcd%’

select id from t where datediff(day,createdate,’2017-09-08′) = 0

    => select id from t where createdate >= ‘2016-11-30‘ and createdate < ‘2016-12-1‘

沒有意義的查詢

原因:

  • 不會返回任何結果集,但是會消耗系統資源。例如:
    • select col1,col2 into #t from t where 1=0
  • select id from t with(index(索引名)) where ID= @id

強制使用索引

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

建議

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

2) 任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。

3) 盡量使用表變量來代替臨時表。如果表變量包含大量數據,請註意索引非常有限(只有主鍵索引)

4) 避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對於一次性事件, 最好使用導出表。

5) 在新建臨時表時,如果一次性插入數據量很大,那麽可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然後insert。

6) 如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。

7) 盡量避免使用遊標,因為遊標的效率較差,如果遊標操作的數據超過1萬行,那麽就應該考慮改寫。

8) 盡量避免大事務操作,提高系統並發能力。

9) 盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

10) 拆分大的 DELETE 或INSERT 語句,批量提交SQL語句。

數據庫常用查詢語句寫法(優化)