寫有效率的SQL查詢(I)

2021-09-05 18:16:42 字數 2548 閱讀 4711

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

這條規則被廣為傳頌,原因據聯機文件和百敬同學的書講,也是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

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

)。這些運算包括字串連線(如: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了。

所謂的「運算」包括加減乘除或通過一些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)

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

寫有效率的SQL查詢(I)

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

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

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