1. 程式人生 > >百萬條數據快速查詢優化技巧參考

百萬條數據快速查詢優化技巧參考

結果集 條件 系統表 log creat 解決方案 fas 一個表 好的

優化並不是絕對,具體得根據業務實際情況

1.應盡量避免在where子句中使用!=或<>操作符

2.應盡量避免在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

3. in 和not in 也要慎用,否則會導致全表掃描

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

對於連續的數值,能用between就不要用in了

如:select id from t where num between 1 and 3

4.下面的查詢也將導致全表掃描

如:select id from t where name like ‘%abc%’

若提高效率,可以考慮全文檢索

5. 如果在where子句中使用參數,也會導致全表掃描。因為sql只有在運行時才會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時,它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:

Select id from t where [email protected]

可以改為強制查詢使用索引:

Select id from t with(index(索引名)) where [email protected]

6.應盡量避免在where子句中對字段進行表達式操作,這將導致引擎放棄使用而進行全表掃描。

如:select if from t where num/2=100

應改為:select id from t where num=100*2

7.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。

如:select id from t where substring(name,1,3)=’abc’ ----name以abc開頭的id

Select id from t where datadiff(day,createdate.’2005-11-30’)=0 ----‘2005-11-30’生成的id

應改為:

Select id from t where name like ‘abc%’

Select id from t where createdate>=’2005-11-30’ and createdate<’2005-12-1’

8.不要在where子句中的”=”左邊進行函數,算術運算或其他表達式運算,否則系統將可能無法正確使用索引

9.在使用索引字段作為條件時,如果該索引是復合索引,那麽必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引不會被使用,並且應盡可能的讓字段順序與索引順序相一致

10. 不要寫一些沒有意義的查詢,如需要生成一個空表結構:

Create table #t(…)

11.很多時候用exist代替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 )

12.並不是所有索引對查詢都有效,sql是根據表中數據來進行優化查詢的,當索引列有大量數據重復時,sql查詢可能不會利用索引,如一表中有字段sex,male,female幾乎各一半,那麽即使在Sex上建了索引也對查詢效率起不了作用

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

14.盡量使用數字型字段,若只含數值信息的字段盡量不要涉及為字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了

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

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

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

18.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗

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

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

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

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

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

24.在所有的存儲過程和觸發器的開始處設置SET NOCOUNT ON ,在結束時設置SET NOCOUNT OFF。無需在執行存儲過程和觸發器的每個語句後在客戶端發送DONE_IN_PROC消息

25.盡量避免大事務操作,提高系統並發能力

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

百萬條數據快速查詢優化技巧參考