**:
掃瞄與查詢操作均是
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條件中的查詢條件來過濾來篩選出滿足條件的資料執行過程。其掃瞄的的物件是表中的所有資料塊,包括空資料庫,如果表中的資料大量被刪除,那麼就會存在大量的空資料塊,再次狀態下,大量的空資料塊也被掃瞄。在執行全表掃瞄時,按照順序每次將多個資料塊從磁碟讀取到...