寫有效率的SQL查詢(I)

2021-04-19 01:05:41 字數 3244 閱讀 4132

io(至於為什麼,回頭補一篇

)。我們常說,「要建彪悍的索引」、「要寫高效的

sql」,其實最終目的就是在相同結果集情況下,盡可能減少邏輯io。

沒統計資訊

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

操作,但實際情況是:

很聰明,它依據統計資訊分析得出來,應該採用

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)

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

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

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