高效SQL查詢之索引(I)

2021-04-28 22:41:15 字數 2907 閱讀 3398

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了。

高效SQL查詢之索引(I)

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

高效SQL查詢之索引(I)

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

基礎演算法 查詢 線性索引查詢(I)

前面介紹的幾種查詢的演算法都是基於資料有序的基礎上進行的。但是在實際的應用中,很多資料集可能有驚人的資料量,面對這些海量的資料,要保證記錄全部按照當中的某個關鍵字有序,其時間代價是非常昂貴的,所以這種資料通常都是按先後順序儲存的。那麼如何能夠快速的查詢到需要的資料呢?辦法就是 索引。索引就是把乙個關...