寫有效率的SQL查詢(I)

2021-04-16 19:21:04 字數 2594 閱讀 6548

1.1where條件的列上都得有統計資訊。

沒統計資訊sqlserver就無法估算不同查詢計畫開銷優劣,而只能採用最穩妥的scan(不管是table scan還是clustered index scan)。一般情況下我們不會犯這種錯誤——where條件裡不使用非索引列是個常識。索引上的統計資訊是無法刪除的。

1.2盡量不使用不等於(!=)或者not邏輯運算子。

這條規則被廣為傳頌,原因據聯機文件和百敬同學的書講,也是sqlserver無法評估不同查詢計畫開銷的優劣。但是sqlserver2k5聰明了很多,試驗發現儘管用了!=或者not,查詢還是會被優化。如下:

create

table tb1 (

col1 int

identity

(1,1)

primary

key,

col2 int

notnull,

col3 varchar

(64)

notnull )

create

index ix_tb1_col2 on tb1 (

col2 )

create

index ix_tb1_col3 on tb1 (

col3 )

declare

@f int

set@f = 0

while

@f < 9999

begin

insert

into tb1 (col2, col3)

values

(1,'ssdd')

set @f = @f + 1

endinsert

into tb1 (col2, col3)

values

(0,'aadddd')

insert

into tb1 (col2, col3)

values

(2,'bbddd')

insert

into tb1 (col2, col3)

values

(3,'bbaaddddddaa')

通過上述**,各位可以看到資料分布。col2值為1的有9999條;col2值為0、2、3的分別有1條。

按照本條規則,!= 和not帶來的應該是個scan操作,但實際情況是:

sql2k5很聰明,它依據統計資訊分析得出來,應該採用index seek而不是index scan。(

稍微解釋解釋

index seek

和index scan

:索引是一顆b樹,

index seek

是查詢從

b樹的根節點開始,一級一級找到目標行。

index scan

則是從左到右,把整個

b樹遍歷一遍。假設唯一的目標行位於索引樹(假設是非聚集索引,樹深度

2,葉節點占用

k頁物理儲存)最右的葉節點上(如上例)。

index seek

引起的io是4

,而index scan

引起的io是k

,效能差別巨大。關於索引,可以仔細讀讀聯機文件關於物理資料庫體系結構部分)。

1.3查詢條件中不要包含運算

這些運算包括字串連線(如:select * from users where username + 『pig』 = 『張**ig』),萬用字元在前面的like運算(如:select * from tb1 where col4 like 『%aa』),使用其他使用者自定義函式、系統內建函式、標量函式等等(如:select * from userlog where datepart(dd, logtime) = 3)。

sqlserver在處理以上語句時,一樣沒辦法估算開銷。最終結果當然是clustered index scan或者table scan了。

1.4查詢條件中不要包含同一張表內不同列之間的運算

所謂的「運算」包括加減乘除或通過一些function(如:select * from tb where col1 – col2 = 1997),也包括比較運算(如:select * from tb where col1 > col2)。這種情況下,sqlserver一樣沒辦法估算開銷。不論col1、col2上都有索引還是建立了col1、col2上的覆蓋索引還是建立了col1 include col2的索引。

但是這種查詢有解決辦法,可以在表上多建立乙個計算字段,其值設定為你的「運算」結果,再在該字段上建立乙個索引,就ok了。

to be continue…

(ii)中將介紹統計資訊值分布不均勻對查詢的影響和如何避免這些影響,捎帶更多的說說返回多行結果時,為啥sqlserver有時會選擇index seek,而有時會選擇index scan。

(iii)中主要介紹傳說中的「foldable」和「nonfoldable」表示式。並舉例說說所謂的「nonfoldable"表示式某些情況下也不是那麼可怕。

(iv)中則主要說說在程式中執行sql。如:安全性,拼sql、引數化sql和儲存過程之間對db來說有什麼區別,引數化sql的一些技巧。捎帶著,會大概介紹介紹sqlserver的buffer pool

寫有效率的SQL查詢(I)

io 至於為什麼,回頭補一篇 我們常說,要建彪悍的索引 要寫高效的 sql 其實最終目的就是在相同結果集情況下,盡可能減少邏輯io。沒統計資訊 sqlserver 就無法估算不同查詢計畫開銷優劣,而只能採用最穩妥的 scan 不管是 table scan 還是clustered index scan...

寫有效率的SQL查詢(I)

沒統計資訊sqlserver就無法估算不同查詢計畫開銷優劣,而只能採用最穩妥的scan 不管是table scan還是clustered index scan 一般情況下我們不會犯這種錯誤 where條件裡不使用非索引列是個常識。索引上的統計資訊是無法刪除的。這條規則被廣為傳頌,原因據聯機文件和百敬...

寫有效率的SQL查詢(2)轉

寫有效率的sql查詢 ii 上回我們說到評估一條語句執行效率主要看邏輯 io 啥是邏輯 io,啥是物理 io見聯機文件 這次我們繼續。我們先說說,返回多行結果時,為什麼 sqlserver 有時會選擇 index seek 有時會選擇 index scan。以 nonclustered index ...