<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    1 SQL Server中的索引

      索引是與表或視圖關聯(lián)的磁盤上結(jié)構,可以加快從表或視圖中檢索行的速度。索引包含由表或視圖中的一列或多列生成的鍵。這些鍵存儲在一個結(jié)構(B 樹)中,使 SQL Server 可以快速有效地查找與鍵值關聯(lián)的行。

      表或視圖可以包含以下類型的索引:

      聚集索引

      聚集索引根據(jù)數(shù)據(jù)行的鍵值在表或視圖中排序和存儲這些數(shù)據(jù)行。索引定義中包含聚集索引列。每個表只能有一個聚集索引,因為數(shù)據(jù)行本身只能按一個順序排序。

      只有當表包含聚集索引時,表中的數(shù)據(jù)行才按排序順序存儲。如果表具有聚集索引,則該表稱為聚集表。如果表沒有聚集索引,則其數(shù)據(jù)行存儲在一個稱為堆的無序結(jié)構中。

      每個表幾乎都對列定義聚集索引來實現(xiàn)下列功能:

      1、可用于經(jīng)常使用的查詢。

      2、提供高度唯一性。

      在創(chuàng)建聚集索引之前,應先了解數(shù)據(jù)是如何被訪問的??紤]對具有以下特點的查詢使用聚集索引:

      使用運算符(如 BETWEEN、>、>=、< 和 <=)返回一系列值。

      使用聚集索引找到包含第一個值的行后,便可以確保包含后續(xù)索引值的行物理相鄰。例如,如果某個查詢在一系列采購訂單號間檢索記 錄,PurchaseOrderNumber 列的聚集索引可快速定位包含起始采購訂單號的行,然后檢索表中所有連續(xù)的行,直到檢索到最后的采購訂單號。

      返回大型結(jié)果集。

      使用 JOIN 子句;一般情況下,使用該子句的是外鍵列。

      使用 ORDER BY 或 GROUP BY 子句。

      在 ORDER BY 或 GROUP BY 子句中指定的列的索引,可以使數(shù)據(jù)庫引擎 不必對數(shù)據(jù)進行排序,因為這些行已經(jīng)排序。這樣可以提高查詢性能。

      聚集索引不適用于具有下列屬性的列:

      頻繁更改的列

      這將導致整行移動,因為數(shù)據(jù)庫引擎 必須按物理順序保留行中的數(shù)據(jù)值。這一點要特別注意,因為在大容量事務處理系統(tǒng)中數(shù)據(jù)通常是可變的。

      寬鍵

      寬鍵是若干列或若干大型列的組合。所有非聚集索引將聚集索引中的鍵值用作查找鍵。為同一表定義的任何非聚集索引都將增大許多,這是因為非聚集索引項包含聚集鍵,同時也包含為此非聚集索引定義的鍵列。 非聚集索引

      非聚集索引具有獨立于數(shù)據(jù)行的結(jié)構。非聚集索引包含非聚集索引鍵值,并且每個鍵值項都有指向包含該鍵值的數(shù)據(jù)行的指針。

      從非聚集索引中的索引行指向數(shù)據(jù)行的指針稱為行定位器。行定位器的結(jié)構取決于數(shù)據(jù)頁是存儲在堆中還是聚集表中。對于堆,行定位器是指向行的指針。對于聚集表,行定位器是聚集索引鍵。

      在 SQL Server 2005 中,可以向非聚集索引的葉級別添加非鍵列以跳過現(xiàn)有的索引鍵限制(900 字節(jié)和 16 鍵列),并執(zhí)行完整范圍內(nèi)的索引查詢。

      非聚集索引與聚集索引具有相同的 B 樹結(jié)構,它們之間的顯著差別在于以下兩點:

      1、基礎表的數(shù)據(jù)行不按非聚集鍵的順序排序和存儲。

      2、非聚集索引的葉層是由索引頁而不是由數(shù)據(jù)頁組成。

      設計非聚集索引時需要注意數(shù)據(jù)庫的特征:

      更新要求較低但包含大量數(shù)據(jù)的數(shù)據(jù)庫或表可以從許多非聚集索引中獲益從而改善查詢性能。

      決策支持系統(tǒng)應用程序和主要包含只讀數(shù)據(jù)的數(shù)據(jù)庫可以從許多非聚集索引中獲益。查詢優(yōu)化器具有更多可供選擇的索引用來確定最快的訪問方法,并且數(shù)據(jù)庫的低更新特征意味著索引維護不會降低性能。

      聯(lián)機事務處理應用程序和包含大量更新表的數(shù)據(jù)庫應避免使用過多的索引。此外,索引應該是窄的,即列越少越好。

      一個表如果建有大量索引會影響 INSERT、UPDATE 和 DELETE 語句的性能,因為所有索引都必須隨表中數(shù)據(jù)的更改進行相應的調(diào)整。

      唯一索引

      唯一索引確保索引鍵不包含重復的值,因此,表或視圖中的每一行在某種程度上是唯一的。

      聚集索引和非聚集索引都可以是唯一索引。

      包含性列索引

      一種非聚集索引,它擴展后不僅包含鍵列,還包含非鍵列。

      索引涵蓋

      指查詢中的SELECT與WHERE子句的所用列同時也屬于非聚集索引的情況。這樣就可以更快檢索數(shù)據(jù),因為所有信息都可以直接來自于索引頁,從而SQL Server可以避免訪問數(shù)據(jù)頁。加上獨立的索引文件組,可以用最快速度訪問數(shù)據(jù)。

      請看如下表示例:

      A.創(chuàng)建簡單非聚集索引 以下示例為 Purchasing.ProductVendor 表的 VendorID 列創(chuàng)建非聚集索引。 

     

          USE AdventureWorks;
      GO
      CREATE INDEX IX_ProductVendor_VendorID
      ON Purchasing.ProductVendor (VendorID);
      GO

      B. 創(chuàng)建簡單非聚集組合索引

      以下示例為 Sales.SalesPerson 表的 SalesQuota 和 SalesYTD 列創(chuàng)建非聚集組合索引。 

     

          CREATE NONCLUSTERED INDEX IX_SalesPerson_SalesQuota_SalesYTD
      ON Sales.SalesPerson (SalesQuota, SalesYTD);
      GO

      C. 創(chuàng)建唯一非聚集索引

      以下示例為 Production.UnitMeasure 表的 Name 列創(chuàng)建唯一的非聚集索引。該索引將強制插入 Name 列中的數(shù)據(jù)具有唯一性。 

     

          USE AdventureWorks;
      GO
      CREATE UNIQUE INDEX AK_UnitMeasure_Name
      ON Production.UnitMeasure(Name);
      GO

      無論何時對基礎數(shù)據(jù)執(zhí)行插入、更新或刪除操作,SQL Server 2005 數(shù)據(jù)庫引擎都會自動維護索引。隨著時間的推移,這些修改可能會導致索引中的信息分散在數(shù)據(jù)庫中(含有碎片)。當索引包含的頁中的邏輯排序(基于鍵值)與數(shù) 據(jù)文件中的物理排序不匹配時,就存在碎片。碎片非常多的索引可能會降低查詢性能,導致應用程序響應緩慢。這個時候,我們需要做得就是重新組織和重新生成索 引。重新生成索引將刪除該索引并創(chuàng)建一個新索引。此過程中將刪除碎片,通過使用指定的或現(xiàn)有的填充因子設置壓縮頁來回收磁盤空間,并在連續(xù)頁中對索引行重 新排序(根據(jù)需要分配新頁)。這樣可以減少獲取所請求數(shù)據(jù)所需的頁讀取數(shù),從而提高磁盤性能。

      可以使用下列方法重新生成聚集索引和非聚集索引:

      帶 REBUILD 子句的 ALTER INDEX。此語句將替換 DBCC DBREINDEX 語句。

      帶 DROP_EXISTING 子句的 CREATE INDEX。

      示例如下:

      A. 重新生成索引

    以下示例將重新生成單個索引。  
          USE AdventureWorks;
      GO
      ALTER INDEX PK_Employee_EmployeeID ON HumanResources.Employee
      REBUILD;
      GO

      B.重新生成表的所有索引并指定選項
      下面的示例指定了 ALL 關鍵字。這將重新生成與表相關聯(lián)的所有索引。其中指定了三個選項?!?/div>
          ALTER INDEX ALL ON Production.Product
      REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON,
      STATISTICS_NORECOMPUTE = ON);
      GO

          2 Oracle 中的索引
      索引是Oracle使用的加速表中數(shù)據(jù)檢索的數(shù)據(jù)庫對象。
      下面的情況,可以考慮使用索引:
      1) 大表
      2) 主鍵(自動索引)
      3) 單鍵列(自動索引)
      4) 外鍵列(自動索引)
      5) 大表上WHERE子句常用的列
      6) ORDER BY 或者GROUP BY子句中使用的列。
      7) 至少返回表中20%行的查詢
      8) 不包含null值的列。
      Oracle中的索引包含有如下幾種類型:
      B*樹索引:這是Oracle中最常用的索引,它的構造類似于二叉樹,能根據(jù)鍵提供一行或一個行集的快速訪問,通常只需要很少的讀操作就能找到正確的行。B*樹索引由兩列組成,第一列是ROWID, 它是行的位置;第二列是正被索引列的值。

      圖:典型的B*樹索引布局

      這個樹底層的塊稱為葉子節(jié)點(leaf node) 或(leaf block),其中分別包含各個索引鍵以及一個rowid(它是指向所索引的行)。葉子節(jié)點之上的內(nèi)部塊稱為分支塊(branch block),這些節(jié)點用于實現(xiàn)導航。例如,如果想在索引中找到值20,要從樹頂開始,找到左分支,我們檢查這個塊,并發(fā)現(xiàn)需要找到范圍"20..25" 的塊,這個塊將是葉子塊,其中會指示包含數(shù)20的行。索引的葉子節(jié)點實際上構成了一個雙向鏈表。一旦發(fā)現(xiàn)要從葉子節(jié)點中的那里開始,執(zhí)行值的有序掃描 (index range scan)就會很容易,我們就不必再在索引結(jié)構中導航:而只需根據(jù)葉子節(jié)點向前或向后掃描就可以了。

      B*樹的特點之一是:所有葉子塊都應該在樹的同一層上,這一層稱之為索引的高度, 它說明所有從索引的根塊到葉子塊的遍歷都會訪問同樣數(shù)目的塊。也就是說,對于形如"SELECT INDEX_column FROM TABLE WHERE INXDEX_column =:X"的索引,要達到葉子塊來獲取第一行,不論使用的:X值是什么,都會執(zhí)行同樣數(shù)目的I/O,由此可見B*樹的B代表的是balanced,所謂的"Height balanced"。大多數(shù)B*樹索引的高度都是2或3,即使索引中有數(shù)百萬行記錄也是如此,這說明,一般而言,在索引中找到一個鍵只需要2到3次I/O , 這確實不錯。

      B*樹是一個極佳的通用索引機制,無論是大表還是小表都很適用,隨著底層表大小增長,獲取數(shù)據(jù)的性能僅會稍有惡化。

      比如,我們?yōu)閏ustomers表建立一個常見的B*樹索引: 

     

          CREATE INDEX IDX_Cus_City on customers(city)

      B*樹索引有以下子類型:

      復合索引

      復合索引也是一種B*樹索引,它由多列組成。當我們擁有使用兩列或超過兩列的頻繁查詢時,就使用B*樹復合索引,而其所使用的兩列或多列在 where子句中and邏輯操作符連接。因為復合索引中列的順序很重要,所以確信以最有效的索引能排列他們,可以參考用作列排序的下面的兩個準則 :

      1) 前導列應該是查詢中使用最頻繁的列。

      2) 前導列應該是選擇最多的列,這意味著它比后面的列具有更高的基數(shù)。

      復合索引在下列情況中具有優(yōu)勢:

      1)假定在WHERE子句中頻繁使用下面的條件:order_status_id = 1 和order_date = ‘dd-mon-yyyy’。如果為每一列創(chuàng)建一個索引,那么為了搜索列的值,兩個索引都要被讀取,但是如果為兩列都創(chuàng)建一個復合索引,那么只有一個索引 被讀取,這樣無疑比兩個索引要求更少的I/O。

      2) 使用前面例子中同樣的條件,如果創(chuàng)建一個復合索引,將更快地檢索行,因為你正在排除了所有order_status_id 不是1的行,從而減少了搜索order_date的行數(shù)。

      反向鍵索引

      B*樹索引的另一個特點是能夠?qū)⑺饕I“反轉(zhuǎn)”。首先,你可以問問自己“為什么想這么做?” B*樹索引是為特定的環(huán)境、特定的問題而設計的。實現(xiàn)B*樹索引的目的是為了減少“右側(cè)”索引中對索引葉子塊的競爭,比如在一個Oracle RAC 環(huán)境中,某些列用一個序列值或時間戳填充,這些列上建立的索引就屬于“右側(cè)”(right-hand-side)索引。

      RAC 是一種Oracle 配置,其中多個實例可以裝載和打開同一個數(shù)據(jù)庫。如果兩個實例需要同時修改同一個數(shù)據(jù)塊,它們會通過一個硬件互連(interconnect)來回傳遞這 個塊來實現(xiàn)共享,互連是兩個(或多個)機器之間的一條專用網(wǎng)絡連接。如果某個利用一個序列填充,這個列上有一個主鍵索引 ,那么每個人插入新值時,都會視圖修改目前索引結(jié)構右側(cè)的左塊(見本文圖一,其中顯示出索引中較高的值都放在右側(cè),而較低的值放在左側(cè))。如果對用序列填 充的列上的索引進行修改,就會聚集在很少的一組葉子塊上。倘若將索引的鍵反轉(zhuǎn),對索引進行插入時,就能在索引中的所有葉子鍵上分布開(不過這往往會使索引 不能得到充分地填充)。

      反向鍵索引創(chuàng)建語句語法如下: 

     

          CREATE INDEX index_name on table_name(column_name) REVERSE ;

      降序索引

      降序索引(descending index)是oracle 8i引入的,用以擴展B*樹索引的功能,它允許在索引中以降序(從大到小的順序)存儲一列。在oracle8i及以上版本中,DESC關鍵字確實會改變創(chuàng)建和使用索引的的方式。

      我們可以這樣創(chuàng)建降序索引

     

          CREATE INDEX IDX_jobs_title on hr.jobs (job_title DESC);
      SET autotrace traceonly EXPLAIN;
      SELECT * FROM hr.jobs
      WHERE job_title Between 'a' AND 'ZZZZZZZZZZZ ';  Execution Plan
      ----------------------------------------------------------
      0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=33)
      1 0 FILTER
      2 1 TABLE ACCESS (BY INDEX ROWID) OF 'JOBS' (Cost=1 Card=1 B
      ytes=33)
      3 2 INDEX (RANGE SCAN) OF 'IDX_JOBS_TITLE' (NON-UNIQUE) (C
      ost=2 Card=1)               
      SQL> SELECT * from hr.jobs
      2 WHERE job_title between 'a' and 'ZZZZZZZZZZZ ';
      Execution Plan
      ----------------------------------------------------------
      0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=33)
      1 0 FILTER
      2 1 TABLE ACCESS (FULL) OF 'JOBS' (Cost=2 Card=1 Bytes=33)
      SQL> DROP INDEX IDX_jobs_title ;
      SQL> CREATE INDEX IDX_jobs_title on hr.jobs (job_title );
      SQL> Select * FROM hr.jobs
      2 Where job_title between 'a' and 'ZZZZZZZZZZZ ';
      Execution Plan
      ----------------------------------------------------------
      0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=33)
      1 0 FILTER
      2 1 TABLE ACCESS (FULL) OF 'JOBS' (Cost=2 Card=1 Bytes=33)

      位圖索引

      位圖索引(bitmap index)是從Oracle7.3 版本開始引入的。目前Oracle企業(yè)版和個人版都支持位圖索引,但標準版不支持。位圖索引是為數(shù)據(jù)倉庫/在線分析查詢環(huán)境設計的,在此所有查詢要求的數(shù)據(jù)在系統(tǒng)實現(xiàn)時根本不知道。位圖索引特別不適用于OLTP 系統(tǒng),如果系統(tǒng)中的數(shù)據(jù)會由多個并發(fā)會話頻繁地更新,這種系統(tǒng)也不適用位圖索引。

      位圖索引是這樣一種結(jié)構,其中用一個索引鍵條目存儲指向多行的指針;這與B*樹結(jié)構不同,在B*樹結(jié)構中,索引鍵和表中的行存在著對應關系。在位圖索引中,可能只有很少的索引條目,每個索引條目指向多行。而在傳統(tǒng)的B*樹中,一個索引條目就指向一行。

      B*樹索引一般來講應當是選擇性的。與之相反,位圖索引不應是選擇性的,一般來講它們應該“沒有選擇性“。如果有大量在線分析查詢,特別是查詢 以一種即席方式引用了多列或者會生成諸如COUNT 之類的聚合,在這樣的環(huán)境中,位圖索引就特別有用 。位圖索引使用 CREATE BITMAP INDEX index_name ON table_name(column_name1,column_name2) TABLESPACE tablespace_name命令語法創(chuàng)建。

     

     

     

     

    SQL Server查詢優(yōu)化技術及索引

    From: http://www.cnblogs.com/lovewindy/archive/2005/02/19/105959.html

     

    在《數(shù)據(jù)庫原理》里面,對聚簇索引的解釋是:聚簇索引的順序就是數(shù)據(jù)的物理存儲順序,而對非聚簇索引的解釋是:索引順序與數(shù)據(jù)物理排列順序無關。正式因為如此,所以一個表最多只能有一個聚簇索引。

    不過這個定義太抽象了。在SQL Server中,索引是通過二叉樹的數(shù)據(jù)結(jié)構來描述的,我們可以這么理解聚簇索引:索引的葉節(jié)點就是數(shù)據(jù)節(jié)點。而非聚簇索引的葉節(jié)點仍然是索引節(jié)點,只不過有一個指針指向?qū)臄?shù)據(jù)塊。如下圖:


    非聚簇索引

     


    聚簇索引


    聚簇索引與非聚簇索引的本質(zhì)區(qū)別到底是什么?什么時候用聚簇索引,什么時候用非聚簇索引?

    這是一個很復雜的問題,很難用三言兩語說清楚。我在這里從SQL Server索引優(yōu)化查詢的角度簡單談談(如果對這方面感興趣的話,可以讀一讀微軟出版的《Microsoft SQL Server 2000數(shù)據(jù)庫編程》第3單元的數(shù)據(jù)結(jié)構引論以及第6、13、14單元)。


    一、索引塊與數(shù)據(jù)塊的區(qū)別

    大家都知道,索引可以提高檢索效率,因為它的二叉樹結(jié)構以及占用空間小,所以訪問速度塊。讓我們來算一道數(shù)學題:如果表中的一條記錄在磁盤上占用1000字節(jié)的話,我們對其中10字節(jié)的一個字段建立索引,那么該記錄對應的索引塊的大小只有10字節(jié)。我們知道,SQL Server的最小空間分配單元是“頁(Page)”,一個頁在磁盤上占用8K空間,那么這一個頁可以存儲上述記錄8條,但可以存儲索引800條?,F(xiàn)在我們要從一個有8000條記錄的表中檢索符合某個條件的記錄,如果沒有索引的話,我們可能需要遍歷8000條×1000字節(jié)/8K字節(jié)=1000個頁面才能夠找到結(jié)果。如果在檢索字段上有上述索引的話,那么我們可以在8000條×10字節(jié)/8K字節(jié)=10個頁面中就檢索到滿足條件的索引塊,然后根據(jù)索引塊上的指針逐一找到結(jié)果數(shù)據(jù)塊,這樣IO訪問量要少的多。


    二、索引優(yōu)化技術

    是不是有索引就一定檢索的快呢?答案是否。有些時候用索引還不如不用索引快。比如說我們要檢索上述表中的所有記錄,如果不用索引,需要訪問8000條×1000字節(jié)/8K字節(jié)=1000個頁面,如果使用索引的話,首先檢索索引,訪問8000條×10字節(jié)/8K字節(jié)=10個頁面得到索引檢索結(jié)果,再根據(jù)索引檢索結(jié)果去對應數(shù)據(jù)頁面,由于是檢索所有數(shù)據(jù),所以需要再訪問8000條×1000字節(jié)/8K字節(jié)=1000個頁面將全部數(shù)據(jù)讀取出來,一共訪問了1010個頁面,這顯然不如不用索引快。

    SQL Server內(nèi)部有一套完整的數(shù)據(jù)檢索優(yōu)化技術,在上述情況下,SQL Server的查詢計劃(Search Plan)會自動使用表掃描的方式檢索數(shù)據(jù)而不會使用任何索引。那么SQL Server是怎么知道什么時候用索引,什么時候不用索引的呢?SQL Server除了日常維護數(shù)據(jù)信息外,還維護著數(shù)據(jù)統(tǒng)計信息,下圖是數(shù)據(jù)庫屬性頁面的一個截圖:

    從圖中我們可以看到,SQL Server自動維護統(tǒng)計信息,這些統(tǒng)計信息包括數(shù)據(jù)密度信息以及數(shù)據(jù)分布信息,這些信息幫助SQL Server決定如何制定查詢計劃以及查詢是是否使用索引以及使用什么樣的索引(這里就不再解釋它們到底如何幫助SQL Server建立查詢計劃的了)。我們還是來做個實驗。建立一張表:tabTest(ID, unqValue,intValue),其中ID是整形自動編號主索引,unqValue是uniqueidentifier類型,在上面建立普通索引,intValue 是整形,不建立索引。之所以掛上一個沒有索引的intValue字段,就是防止SQL Server使用索引覆蓋查詢優(yōu)化技術,這樣實驗就起不到作用了。向表中錄入10000條隨機記錄,代碼如下:

     

    CREATE TABLE [dbo].[tabTest] (
     
    [ID] [int] IDENTITY (11NOT NULL ,
     
    [unqValue] [uniqueidentifier] NOT NULL ,
     
    [intValue] [int] NOT NULL 
    ON [PRIMARY]
    GO

    ALTER TABLE [dbo].[tabTest] WITH NOCHECK ADD 
     
    CONSTRAINT [PK_tabTest] PRIMARY KEY  CLUSTERED 
     (
      
    [ID]
     )  
    ON [PRIMARY] 
    GO

    ALTER TABLE [dbo].[tabTest] ADD 
     
    CONSTRAINT [DF_tabTest_unqValue] DEFAULT (newid()) FOR [unqValue]
    GO

    CREATE  INDEX [IX_tabTest_unqValue] ON [dbo].[tabTest]([unqValue]ON [PRIMARY]
    GO

    declare @i int
    declare @v int

    set @i=0
    while @i<10000
    begin
        
    set @v=rand()*1000    
        
    insert into tabTest ([intValue]values (@v)
        
    set @i=@i+1
    end

     

    然后我們執(zhí)行兩個查詢并查看執(zhí)行計劃,如圖:(在查詢分析器的查詢菜單中可以打開查詢計劃,同時圖上第一個查詢的GUID是我從數(shù)據(jù)庫中找的,大家做實驗的時候可以根據(jù)自己數(shù)據(jù)庫中的值來定):



    從圖中可以看出,在第一個查詢中,SQL Server使用了IX_tabTest_unqValue索引,根據(jù)箭頭方向,計算機先在索引范圍內(nèi)找,找到后,使用Bookmark Lookup將索引節(jié)點映射到數(shù)據(jù)節(jié)點上,最后給出SELECT結(jié)果。在第二個查詢中,系統(tǒng)直接遍歷表給出結(jié)果,不過它使用了聚簇索引,為什么呢?不要忘了,聚簇索引的頁節(jié)點就是數(shù)據(jù)節(jié)點!這樣使用聚簇索引會更快一些(不受數(shù)據(jù)刪除、更新留下的存儲空洞的影響,直接遍歷數(shù)據(jù)是要跳過這些空洞的)。

    下面,我們在SQL Server中將ID字段的聚簇索引更改為非聚簇索引,然后再執(zhí)行select * from tabTest,這回我們看到的執(zhí)行計劃變成了:

    SQL Server沒有使用任何索引,而是直接執(zhí)行了Table Scan,因為只有這樣,檢索效率才是最高的。


    三、聚簇索引與非聚簇索引的本質(zhì)區(qū)別

    現(xiàn)在可以討論聚簇索引與非聚簇索引的本質(zhì)區(qū)別了。正如本文最前面的兩個圖所示,聚簇索引的葉節(jié)點就是數(shù)據(jù)節(jié)點,而非聚簇索引的頁節(jié)點仍然是索引檢點,并保留一個鏈接指向?qū)獢?shù)據(jù)塊。

    還是通過一道數(shù)學題來看看它們的區(qū)別吧:假設有一8000條記錄的表,表中每條記錄在磁盤上占用1000字節(jié),如果在一個10字節(jié)長的字段上建立非聚簇索引主鍵,需要二叉樹節(jié)點16000個(這16000個節(jié)點中有8000個葉節(jié)點,每個頁節(jié)點都指向一個數(shù)據(jù)記錄),這樣數(shù)據(jù)將占用8000條×1000字節(jié)/8K字節(jié)=1000個頁面;索引將占用16000個節(jié)點×10字節(jié)/8K字節(jié)=20個頁面,共計1020個頁面。

    同樣一張表,如果我們在對應字段上建立聚簇索引主鍵,由于聚簇索引的頁節(jié)點就是數(shù)據(jù)節(jié)點,所以索引節(jié)點僅有8000個,占用10個頁面,數(shù)據(jù)仍然占有1000個頁面。

    下面我們看看在執(zhí)行插入操作時,非聚簇索引的主鍵為什么比聚簇索引主鍵要快。主鍵約束要求主鍵不能出現(xiàn)重復,那么SQL Server是怎么知道不出現(xiàn)重復的呢?唯一的方法就是檢索。對于非聚簇索引,只需要檢索20個頁面中的16000個節(jié)點就知道是否有重復,因為所有主鍵鍵值在這16000個索引節(jié)點中都包含了。但對于聚簇索引,索引節(jié)點僅僅包含了8000個中間節(jié)點,至于會不會出現(xiàn)重復必須檢索另外1000個頁數(shù)據(jù)節(jié)點才知道,那么相當于檢索10+1000=1010個頁面才知道是否有重復。所以聚簇索引主鍵的插入速度要比非聚簇索引主鍵的插入速度慢很多。

    讓我們再來看看數(shù)據(jù)檢索的效率,如果對上述兩表進行檢索,在使用索引的情況下(有些時候SQL Server執(zhí)行計劃會選擇不使用索引,不過我們這里姑且假設一定使用索引),對于聚簇索引檢索,我們可能會訪問10個索引頁面外加1000個數(shù)據(jù)頁面得到結(jié)果(實際情況要比這個好),而對于非聚簇索引,系統(tǒng)會從20個頁面中找到符合條件的節(jié)點,再映射到1000個數(shù)據(jù)頁面上(這也是最糟糕的情況),比較一下,一個訪問了1010個頁面而另一個訪問了1020個頁面,可見檢索效率差異并不是很大。所以不管非聚簇索引也好還是聚簇索引也好,都適合排序,聚簇索引僅僅比非聚簇索引快一點。


    結(jié)語

    好了,寫了半天,手都累了。關于聚簇索引與非聚簇索引效率問題的實驗就不做了,感興趣的話可以自己使用查詢分析器對查詢計劃進行分析。SQL Server是一個很復雜的系統(tǒng),尤其是索引以及查詢優(yōu)化技術,Oracle就更復雜了。了解索引以及查詢背后的事情不是什么壞事,它可以幫助我們更為深刻的了解我們的系統(tǒng)。

     

     

    SQL Server基礎知識之:設計和實現(xiàn)視圖

    設計和實現(xiàn)視圖可謂是數(shù)據(jù)庫物理設計中的一個非常重要的步驟。從一般意義上說,設計和實現(xiàn)視圖應該遵循下面的一些建議和原則。

    以下內(nèi)容摘在文檔,我對某些重點進行了補充說明(紅色部分)

  • 只能在當前數(shù)據(jù)庫中創(chuàng)建視圖。 但是,如果使用分布式查詢定義視圖,則新視圖所引用的表和視圖可以存在于其他數(shù)據(jù)庫甚至其他服務器中。
    • 分布式視圖是可行的,但隨著SQL Server本身能力的提高,例如SQL Server 2005開始支持表分區(qū)等技術之后,分布式視圖應該盡量少用。
    • 所謂分布式視圖的一個最大的問題就是將表物理上分開在多個數(shù)據(jù)庫甚至服務器中,這增加了維護和查詢的難度
  • 視圖名稱必須遵循標識符的規(guī)則,且對每個架構都必須唯一。 此外,該名稱不得與該架構包含的任何表的名稱相同。
    • 一個可以借鑒的做法是:在視圖名稱之前添加一個前綴 vw
  • 您可以對其他視圖創(chuàng)建視圖。Microsoft SQL Server 允許嵌套視圖。但嵌套不得超過 32 層。 根據(jù)視圖的復雜性及可用內(nèi)存,視圖嵌套的實際限制可能低于該值。
    • 一般不建議超過2層
  • 不能將規(guī)則或 DEFAULT 定義與視圖相關聯(lián)。
  • 不能將 AFTER 觸發(fā)器與視圖相關聯(lián),只有 INSTEAD OF 觸發(fā)器可以與之相關聯(lián)。
    • 除非萬不得已,一般不建議使用觸發(fā)器
  • 定義視圖的查詢不能包含 COMPUTE 子句、COMPUTE BY 子句或 INTO 關鍵字。
    • 很多朋友不知道:COMPUTER和COMPUTER BY語句僅僅用于一些特殊場合,用于生成總計行。大致有如下的效果

    image

    該特性不能用于視圖,但可以直接用于查詢

     

  • 定義視圖的查詢不能包含 ORDER BY 子句,除非在 SELECT 語句的選擇列表中還有一個 TOP 子句。
    • 這個很有意思,如果要訪問所有的呢,還必須是寫TOP 100 PERCENT
  • 定義視圖的查詢不能包含指定查詢提示的 OPTION 子句。
  • 定義視圖的查詢不能包含 TABLESAMPLE 子句。
    • 關于TABLESAMPLE語句,大家可能也比較陌生,這是一個用于對數(shù)據(jù)進行抽樣的。它和TOP語句不同,TOP語句是有固定大小的,而TABLESAMPLE返回的數(shù)據(jù),可能多,可能少,甚至可能沒有
    • 我之前有一篇文章講述這個語法 http://www.cnblogs.com/chenxizhang/archive/2009/05/19/1460040.html
  • 不能為視圖定義全文索引定義。
  • 不能創(chuàng)建臨時視圖,也不能對臨時表創(chuàng)建視圖。
    • 在SQL Server 2005中,可以通過CTE(Common Table Expression)來實現(xiàn)該功能
    • 之前的版本,大致的做法是使用臨時表,表變量,函數(shù)等等
  • 不能刪除參與到使用 SCHEMABINDING 子句創(chuàng)建的視圖中的視圖、表或函數(shù),除非該視圖已被刪除或更改而不再具有架構綁定。 另外,如果對參與具有架構綁定的視圖的表執(zhí)行 ALTER TABLE 語句,而這些語句又會影響該視圖的定義,則這些語句將會失敗。
    • 如果未使用 SCHEMABINDING 子句創(chuàng)建視圖,則對視圖下影響視圖定義的對象進行更改時,應運行 sp_refreshview。 否則,當查詢視圖時,可能會生成意外結(jié)果。
    • 強烈建議對某些非常重要的視圖,添加SCHEMABINDING 子句。

    image

  • 盡管查詢引用一個已配置全文索引的表時,視圖定義可以包含全文查詢,仍然不能對視圖執(zhí)行全文查詢。
  • 下列情況下必須指定視圖中每列的名稱:
    • 視圖中的任何列都是從算術表達式、內(nèi)置函數(shù)或常量派生而來。
    • 視圖中有兩列或多列原應具有相同名稱(通常由于視圖定義包含聯(lián)接,因此來自兩個或多個不同表的列具有相同的名稱)。
    • 希望為視圖中的列指定一個與其源列不同的名稱。 (也可以在視圖中重命名列。) 無論重命名與否,視圖列都會繼承其源列的數(shù)據(jù)類型。

      若要創(chuàng)建視圖,您必須獲取由數(shù)據(jù)庫所有者授予的此操作執(zhí)行權限,如果使用 SCHEMABINDING 子句創(chuàng)建視圖,則必須對視圖定義中引用的任何表或視圖具有相應的權限。

      默認情況下,由于行通過視圖進行添加或更新,當其不再符合定義視圖的查詢的條件時,它們即從視圖范圍中消失。 例如,創(chuàng)建一個定義視圖的查詢,該視圖從表中檢索員工的薪水低于 $30,000 的所有行。如果員工的薪水漲到 $32,000,因其薪水不符合視圖所設條件,查詢時視圖不再顯示該特定員工。 但是,WITH CHECK OPTION 子句強制所有數(shù)據(jù)修改語句均根據(jù)視圖執(zhí)行,以符合定義視圖的 SELECT 語句中所設條件。 如果使用該子句,則對行的修改不能導致行從視圖中消失。 任何可能導致行消失的修改都會被取消,并顯示錯誤。

     

  • 作者: 王德田 發(fā)表于 2011-03-07 16:37 原文鏈接

    評論: 0 查看評論 發(fā)表評論


    最新新聞:
    · 疑似中國黑客入侵澳大利亞議會計算機系統(tǒng)(2011-03-29 12:05)
    · 蘋果開發(fā)者大會1599美元天價門票搶購一空(2011-03-29 12:04)
    · 樂淘網(wǎng)CEO畢勝:今年近七成廣告預算投向搜索(2011-03-29 11:58)
    · Facebook聘請時代華納高管提升廣告服務(2011-03-29 11:57)
    · “萬能膠之父”逝世 曾被奧巴馬頒科技獎(2011-03-29 11:56)

    編輯推薦:Java之父詹姆斯·高斯林加盟Google

    網(wǎng)站導航:博客園首頁  我的園子  新聞  閃存  小組  博問  知識庫

    posted on 2011-03-07 16:37 sanmao 閱讀(2252) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     

    常用鏈接

    留言簿(5)

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 无码日韩精品一区二区免费暖暖 | 亚洲无线码在线一区观看| 亚洲色偷偷色噜噜狠狠99网| 日本视频一区在线观看免费| 亚洲色图.com| 69堂人成无码免费视频果冻传媒| 91香蕉国产线在线观看免费| 亚洲欧洲一区二区| 99久久久国产精品免费无卡顿| 亚洲一区在线视频| 成人免费a级毛片无码网站入口 | 在线观看91精品国产不卡免费| 亚洲精品伦理熟女国产一区二区| 日本a级片免费看| 亚洲精品黄色视频在线观看免费资源| 国产综合精品久久亚洲| 日本一卡精品视频免费| 亚洲另类精品xxxx人妖| 国产精品酒店视频免费看| 九九全国免费视频| 久久久久亚洲AV成人无码| 国产91色综合久久免费| 亚洲成av人在线观看网站| 国产午夜亚洲不卡| 37pao成人国产永久免费视频| 亚洲人成人77777网站不卡| 国产免费久久精品| 国内精品免费在线观看 | 国产亚洲美女精品久久| 国产亚洲精品资源在线26u| 在线视频免费观看爽爽爽| 日本系列1页亚洲系列| 亚洲阿v天堂在线| 成全高清视频免费观看| 中文字幕在线免费观看视频| 亚洲高清视频免费| 亚洲国产成人精品女人久久久| 久久A级毛片免费观看| 国产亚洲Av综合人人澡精品| 亚洲国产综合精品中文第一区| 免费羞羞视频网站|