索引掃瞄與索引查詢區別

2022-02-14 21:50:32 字數 3652 閱讀 1876

**:

掃瞄與查詢操作均是

sqlserver

從表或索引中讀取資料採用的迭代器,這些也是

sql server

支援的最基本的運算.幾乎在每乙個查詢計畫中都可以找到,因此理解它們的不同是很重要的,掃瞄是在整張表上進行處理,而索引是在整個頁級上進行處理,而查詢則返回特定謂詞上乙個或多個範圍內的資料行.

下面讓我們看乙個掃瞄的例子(這裡使用

northwind

資料庫)

select [orderid] from [orders] where [requireddate] = '1998-03-26'
在orders

表中,並不存在對

requireddate

列的索引,因此,

sql server

必須讀取

orders

表的每一行來估計每一行的

requireddate

謂詞,如果滿足該謂詞條件(即找到包含

』1998-03-26』

的記錄),則返回該行資料.

為了最大化提公升效能,

sql server

盡可能地使用掃瞄迭代器來估計該謂詞,然而,如果該謂詞過於複雜或開銷過大,

sql server

或許使用別的篩選迭代器來估計.以下是

where

關鍵字中的文字計畫的過程:

--clustered index scan(object:([orders].[pk_orders]),where:([orders].[requireddate]='1998-03-26'))

由於掃瞄表的每一行資料,不論滿足與否,因此,其查詢開銷對錶中的總記錄數是均衡的,當表中的資料很少或滿足謂詞的行比較多時,採用掃瞄操作有效,如果表中資料量比較大或滿足謂詞的行較少時,使用掃瞄將讀取更多的頁面或執行更多的

i/o操作來獲取資料,這顯而不是最有效的方法.

下面讓我們看乙個關於索引查詢的例子,下面的例子在

orderddate

列上建立了索引:

select [orderid] from [orders] where [orderdate] = '1998-02-26'
這次sql server

能夠使用索引查詢來直接找到滿足謂詞的那些記錄行,這裡稱該謂詞為"查詢"謂詞.大多數情況下,

sql server

並不顯式地估計"查詢"謂詞,而索引確保了"查詢"操作僅返回滿足的資料行,以下是"查詢"謂詞的文字計畫:

--index seek(object:([orders].[orderdate]),seek:([orders].[orderdate]=convert_implicit(datetime,[@1],0)) ordered forward)
注意:sql server

自動使用@

1引數替換查詢文字中的引數

由此看來,查詢僅掃瞄滿足該謂詞的資料頁,其查詢開銷顯然要比表中總記錄數的開銷低,因此,對於高選擇度的查詢謂詞操作,查詢通常是最有效的策略.也就是說,對於估計大表中的資料時,使用查詢謂詞是比較有效率的.

sql server

將掃瞄與查詢進行區分,如同將在堆(無聚集索引的物件)上掃瞄,聚集索引上的掃瞄,非聚集索引上的掃瞄進行分割槽.下表說明了這些出現在的查詢計畫中的掃瞄與查詢運算.

掃瞄

查詢

表掃瞄聚集索引

聚集索引找描

聚集索引查詢

非聚集索引

索引掃瞄

索引查詢

可查詢的謂詞與覆蓋列

sql server

在執行索引查詢之前,它需要確定索引的鍵是否滿足查詢中的謂詞,我們稱該謂詞為"可查詢的謂詞",

sql server

必須確定該索引是否包含或"覆蓋"查詢中引用的列集合.下面描述了如何確定哪個謂詞是可查詢的,哪個謂詞不是可查詢的,哪些列需要索引覆蓋.

單列索引

在單列索引上判斷謂詞是否是可查詢的是很容易的,

sql server

使用單列索引來響應多數簡單的比較(包括相等和不等(大於,小於等))或者更複雜的表示式,如在列上運算的函式和

like %

謂詞,這些運算子將阻止

sql server

使用索引查詢.

例如,假設我們在

col1

列上建立了單列索引,可以在以下謂詞上進行索引查詢:

ø[col1] = 3.14

ø[col1] > 100

ø[col1] between 0 and 99

ø[col1] like 'abc%'

ø[col1] in (2, 3, 5, 7)

然頁,在以下謂詞上將不能使用索引查詢:

øabs([col1]) = 1

ø[col1] + 1 = 9

ø[col1] like '%abc'

下面我通過一些例子來介紹單列索引:

首先建立一些架構物件:

create table person(id int, last_name varchar(30), first_name varchar(30))

create unique clustered index person_id on person (id)

create index person_name on person (last_name, first_name)

以下是三個查詢及其各自的文字查詢計畫,第乙個查詢在

person_name

索引上進行查詢,第二個查詢首先在第乙個鍵列上進行索引查詢,然後使用

residual

謂詞來估計

first_name,

第三個查詢不能使用索引查詢,而是使用了索引掃瞄來處理

residual

謂詞.

select id from person where last_name = 'doe' and first_name = 'john'

--index seek(object:([person].[person_name]), seek:([person].[last_name]='doe' and [person].[first_name]='john'))

select id from person where last_name > 'doe' and first_name = 'john'

--index seek(object:([person].[person_name]), seek:([person].[last_name] > 'doe'), where:([person].[first_name]='john'))

select id from person where last_name like '%oe' and first_name = 'john'

--index scan(object:([person].[person_name]), where:([person].[first_name]='john' and [person].[last_name] like '%oe'))

索引查詢和索引掃瞄

索引的訪問方式主要是 索引查詢 索引掃瞄。在執行計畫中為 index seek,適用於查詢少量資料。對應隨機io,能快速的定位一條資料。在執行計畫中為 index scan,適合掃瞄整個索引的資料。類似於全表掃瞄 只掃瞄索引 對應順序io,io效率本身比較高。索引查詢 和 索引掃瞄,單從io效率上來...

索引掃瞄總是索引掃瞄麼?

問 使用nc掃瞄運算子,有方法知道索引是怎麼掃瞄的麼?這個問題的乙個答案是非聚集索引掃瞄總是掃瞄整個索引。答 是的,總是100 掃瞄運算子總是整個索引 但是有一些特定的情況並不是這樣。在這篇文章裡我想專門講下你總會碰到的乙個特定案例 在你的查詢裡有top,min或者max表示式。我們來看下面2個查詢...

全表掃瞄與索引掃瞄

一,全表掃瞄 全表掃瞄是從讀取資料的同時通過where條件中的查詢條件來過濾來篩選出滿足條件的資料執行過程。其掃瞄的的物件是表中的所有資料塊,包括空資料庫,如果表中的資料大量被刪除,那麼就會存在大量的空資料塊,再次狀態下,大量的空資料塊也被掃瞄。在執行全表掃瞄時,按照順序每次將多個資料塊從磁碟讀取到...