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 ...