The NoteBook of EricKong

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

               掃描與查找操作均是SQL Server從表或索引中讀取數(shù)據(jù)采用的迭代器,這些也是SQL Server支持的最基本的運(yùn)算.幾乎在每一個(gè)查詢計(jì)劃中都可以找到,因此理解它們的不同是很重要的,掃描是在整張表上進(jìn)行處理,而索引是在整個(gè)頁級(jí)上進(jìn)行處理,而查找則返回特定謂詞上一個(gè)或多個(gè)范圍內(nèi)的數(shù)據(jù)行
                下面讓我們看一個(gè)掃描的例子(這里使用Northwind數(shù)據(jù)庫)
                  SELECT [OrderId] FROM [Orders] WHERE [RequiredDate] = '1998-03-26'
                  在Orders表中,并不存在對(duì)RequiredDate列的索引,因此,SQL Server必須讀取Orders表的每一行來估計(jì)每一行的RequiredDate謂詞,如果滿足該謂詞條件(即找到包含’1998-03-26’的記錄),則返回該行數(shù)據(jù).
                  為了最大化提升性能,SQL Server盡可能地使用掃描迭代器來估計(jì)該謂詞,然而,如果該謂詞過于復(fù)雜或開銷過大,SQL Server或許使用別的篩選迭代器來估計(jì).以下是WHERE關(guān)鍵字中的文本計(jì)劃的過程:
          |--Clustered Index Scan(OBJECT:([Orders].[PK_Orders]),
            WHERE:([Orders].[RequiredDate]='1998-03-26'))
          下圖描述了該操作的流程圖:

              由于掃描表的每一行數(shù)據(jù),不論滿足與否,因此,其查詢開銷對(duì)表中的總記錄數(shù)是均衡的,當(dāng)表中的數(shù)據(jù)很少或滿足謂詞的行比較多時(shí),采用掃描操作有效,如果表中數(shù)據(jù)量比較大或滿足謂詞的行較少時(shí),使用掃描將讀取更多的頁面或執(zhí)行更多的I/O操作來獲取數(shù)據(jù),這顯而不是最有效的方法.   
               下面讓我們看一個(gè)關(guān)于索引查找的例子,下面的例子在OrderdDate列上創(chuàng)建了索引:
             SELECT [OrderId] FROM [Orders] WHERE [OrderDate] = '1998-02-26'

                   這次SQL Server能夠使用索引查找來直接找到滿足謂詞的那些記錄行,這里稱該謂詞為"查找"謂詞.大多數(shù)情況下,SQL Server并不顯式地估計(jì)"查找"謂詞,而索引確保了"查找"操作僅返回滿足的數(shù)據(jù)行,以下是"查找"謂詞的文本計(jì)劃:

          |--Index Seek(OBJECT:([Orders].[OrderDate]),

            SEEK:([Orders].[OrderDate]=CONVERT_IMPLICIT(datetime,[@1],0)) ORDERED FORWARD)

          注意:SQL Server自動(dòng)使用@1參數(shù)替換查詢文本中的參數(shù)

              由此看來,查找僅掃描滿足該謂詞的數(shù)據(jù)頁,其查詢開銷顯然要比表中總記錄數(shù)的開銷低,因此,對(duì)于高選擇度的查詢謂詞操作,查找通常是最有效的策略.也就是說,對(duì)于估計(jì)大表中的數(shù)據(jù)時(shí),使用查找謂詞是比較有效率的.

              SQL Server將掃描與查找進(jìn)行區(qū)分,如同將在堆(無聚集索引的對(duì)象)上掃描,聚集索引上的掃描,非聚集索引上的掃描進(jìn)行分區(qū).下表說明了這些出現(xiàn)在的查詢計(jì)劃中的掃描與查找運(yùn)算.

           

          掃描

          查找

          表掃描

           

          聚集索引

          聚集索引找描

          聚集索引查找

          非聚集索引

          索引掃描

          索引查找

          可查找的謂詞與覆蓋列

              SQL Server在執(zhí)行索引查找之前,它需要確定索引的鍵是否滿足查詢中的謂詞,我們稱該謂詞為"可查找的謂詞",SQL Server必須確定該索引是否包含或"覆蓋"查詢中引用的列集合.下面描述了如何確定哪個(gè)謂詞是可查找的,哪個(gè)謂詞不是可查找的,哪些列需要索引覆蓋.

          單列索引

             在單列索引上判斷謂詞是否是可查找的是很容易的,SQL Server使用單列索引來響應(yīng)多數(shù)簡單的比較(包括相等和不等(大于,小于等))或者更復(fù)雜的表達(dá)式,如在列上運(yùn)算的函數(shù)和LIKE %謂詞,這些運(yùn)算符將阻止SQL Server使用索引查找.

          例如,假設(shè)我們?cè)贑ol1列上創(chuàng)建了單列索引,可以在以下謂詞上進(jìn)行索引查找:

          Ø [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'

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

          首先創(chuàng)建一些架構(gòu)對(duì)象:
          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)

              以下是三個(gè)查詢及其各自的文本查詢計(jì)劃,第一個(gè)查詢?cè)趐erson_name索引上進(jìn)行查找,第二個(gè)查詢首先在第一個(gè)鍵列上進(jìn)行索引查找,然后使用residual謂詞來估計(jì)first_name,第三個(gè)查詢不能使用索引查找,而是使用了索引掃描來處理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'))

           

          上面三條查詢的圖形查詢計(jì)劃:

          posted on 2010-08-18 16:16 Eric_jiang 閱讀(2374) 評(píng)論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫
          主站蜘蛛池模板: 泰宁县| 独山县| 晋江市| 鄱阳县| 军事| 兰考县| 潮安县| 栖霞市| 汨罗市| 巢湖市| 银川市| 丰镇市| 峨边| 隆子县| 孝昌县| 荣成市| 安陆市| 会东县| 永春县| 庆安县| 吴堡县| 谷城县| 怀柔区| 平顺县| 武功县| 商丘市| 紫云| 潼关县| 鲁山县| 共和县| 木兰县| 通化县| 建始县| 秀山| 安阳市| 梓潼县| 库车县| 嫩江县| 永嘉县| 丽水市| 惠来县|