1. 程式人生 > >資料庫查詢速度優化之解決技巧

資料庫查詢速度優化之解決技巧

1、對查詢進行優化,應儘可能避免全表掃描

首先應考慮在 where 及 order by 涉及的列上建立索引。 
下面我們來以一個表中177條資料比較一下,全表掃描與建立索引之後效能的一個比較.

1.1 全表查詢

這裡寫圖片描述

1.2 建立索引查詢

這裡寫圖片描述

1.3 結論

從這兩種方式查詢資料庫結果看,建立索引之後查詢速度提高了些,現在資料量還不明顯,如果表中有10萬條速度,差異就會很明顯了.

2、寫資料語句時儘可能減少表的全域性掃描

2.1 減少where 欄位值null判斷

SELECT * FROM "tb_real_time_car" where pay_status = null
  • 1

如何這樣做,就會導致引擎放棄使用索引而進行全表掃描 
應該這樣去設定(也就是在沒有值時,我們在存資料庫時自動預設給個o值,而不是什麼都不寫):

SELECT * FROM "tb_real_time_car" where pay_status = 0
  • 1

2.2 應儘量避免在 where 子句中使用!=或<>操作符

SELECT * FROM "tb_real_time_car" where pay_status != null ;
//或者
SELECT * FROM "tb_real_time_car" where pay_status <> null ;
  • 1
  • 2
  • 3

這樣寫將導致引擎放棄使用索引而進行全表掃描。

2.3 應儘量避免在 where 子句中使用 or 來連線條件

SELECT * FROM "tb_real_time_car" where pay_status != null or enter_time = null; 
  • 1

這樣將導致引擎放棄使用索引而進行全表掃描

可以這樣操作:

SELECT * FROM "tb_real_time_car" where pay_status != null union all 
SELECT * FROM "tb_real_time_car" where enter_time = null; 
  • 1
  • 2

2.4 in 和 not in 也要慎用

SELECT * FROM "tb_real_time_car" where rowed in [1,2,3,4]; 
//或者
SELECT * FROM "tb_real_time_car" where rowed not in [1,2,3,4]; 
  • 1
  • 2
  • 3

這樣操作,也會導致全表掃描

可以這樣來寫:

SELECT * FROM "tb_real_time_car" where rowed between 1 and 5; 
  • 1

2.5 少使用模糊匹配 like

SELECT * FROM "tb_real_time_car" where enter_time like '%2016-09-01%'
  • 1

2.6 應儘量避免在 where 子句中對欄位進行表示式操作

SELECT * FROM "tb_real_time_car" where rowid/4 =100;
  • 1

這樣寫,將導致引擎放棄使用索引而進行全表掃描

應該寫成:

SELECT * FROM "tb_real_time_car" where rowid =4*100;
  • 1

2.7 任何地方都不要使用*萬用字元去查詢所有

SELECT * FROM "tb_real_time_car" where rowid/4 =100;
  • 1

以萬用字元*去查詢所有資料,這樣做也是非常耗時的,我們應該需要什麼欄位就查詢什麼欄位.

應該這樣做:

SELECT leave_time FROM "tb_real_time_car" where rowid/4 =100;
  • 1

3、不要在條件判斷時進行 算數運算

SELECT * FROM "tb_real_time_car" where rowid/4 =100;
  • 1

所以不要在 where 子句中的“=”左邊進行函式、算術運算或其他表示式運算,這樣系統將可能無法正確使用索引

應該這樣做:

SELECT * FROM "tb_real_time_car" where rowed =400;
  • 1

4、很多時候用 exists 代替 in 是一個好的選擇

SELECT * FROM "tb_real_time_car" where rowed (select rowed from "tb_real");
  • 1

應該這樣來寫:

SELECT * FROM "tb_real_time_car" where exists (select rowed from "tb_real" where rowed = tb_real.rowid);
  • 1

5 論索引技巧

5.1 並不是所有索引對查詢都有效

SQL是根據表中資料來進行查詢優化的,當索引列有大量資料重複時,SQL查詢可能不會去利用索引,如一表中有欄位sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用

5.2 索引並不是越多越好

索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

5.3 應儘可能的避免更新 clustered 索引資料列

因為 clustered 索引資料列的順序就是表記錄的物理儲存順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引資料列,那麼需要考慮是否應將該索引建為 clustered 索引。

5.4 儘量使用數字型欄位

若只含數值資訊的欄位儘量不要設計為字元型,這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連線時會逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。

5 建立資料庫時應該注意地方

5.1. 儘可能的使用 varchar/nvarchar 代替 char/nchar

因為首先變長欄位儲存空間小,可以節省儲存空間,其次對於查詢來說,在一個相對較小的欄位內搜尋效率顯然要高些。

5.2 用表變數來代替臨時表。

1. 如果表變數包含大量資料,請注意索引非常有限(只有主鍵索引)。

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

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

3 避免頻繁建立和刪除臨時表,以減少系統表資源的消耗。

4 儘量避免使用遊標

1. 因為遊標的效率較差,如果遊標操作的資料超過1萬行,那麼就應該考慮改寫。

2. 使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。

3. 與臨時表一樣,遊標並不是不可使用。對小型資料集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的資料時。在結果集中包括“合計”的例程通常要比使用遊標執行的速度快。如果開發時間允許,基於遊標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。

6 資料放回時注意什麼

6.1 儘量避免大事務操作,提高系統併發能力。

這樣可以有效提高系統的併發能力

6.2 儘量避免向客戶端返回大資料量

若資料量過大,應該考慮相應需求是否合理。

7.總結

我們做專案時 在做專案優化時我們要注意這些效能問題,上面我是結合了之前做專案遇到的問題以及綜合了別人的看法.