SQL Server索引簡介:SQL Server索引級別1

索引是數據庫設計的基礎,並告訴開發人員使用數據庫關於設計者的意圖。不幸的是,當性能問題出現時,索引每每被添加爲過後考慮。這裏最後是一個簡單的系列文章,應該使他們快速地使任何數據庫專業人員「快速」sql

第一級引入SQL Server索引:使SQL Server可以在最短的時間內找到和/或修改請求的數據的數據庫對象,使用最少的系統資源來實現最高性能。良好的索引也將容許SQL Server實現最大的併發性,以便由一個用戶運行的查詢對其餘人運行的查詢影響不大。最後,經過在建立惟一索引時保證鍵值的惟一性,索引提供了強制執行數據完整性的有效方式。這個級別是一個介紹;它涵蓋了概念和用法,但將物理細節留在較晚的級別。數據庫

對於數據庫開發人員來講,深刻理解索引是很是重要的:出於某種緣由,數據庫開發人員最重要的是:當SQL Server的請求從客戶端到達時,SQL Server只有兩種可能的方式來訪問請求的行:併發

l ·它能夠掃描包含數據的表中的每一行,從第一行開始並繼續到最後一行,檢查每一行,看它是否符合請求標準。數據庫設計

l ·或者,若是有有用的索引可用,則可使用索引來查找所請求的數據。性能

第一個選項老是可用於SQL Server。第二個選項僅在您指示SQL Server建立有益的索引時纔可用,但能夠顯着提升性能,咱們將在後面的層次中進行說明。ui

因爲索引具備與它們相關的開銷(它們佔用空間而且必須與表保持同步),所以SQL Server不須要它們。能夠有一個沒有索引的數據庫。它可能執行得不好,確定會有數據完整性問題,但SQL Server將容許它。spa

可是,這不是咱們想要的。咱們都但願數據庫性能良好,具備數據完整性,同時將索引開銷降到最低。這個水平將使咱們朝着這個目標前進。設計

示例數據庫對象

在整個StairWay中,咱們將用例子來講明關鍵的概念。這些示例基於Microsoft AdventureWorks示例數據庫。咱們專一於銷售訂單功能。五張表將給咱們交易和非交易數據的良好組合; Customer,SalesPerson,Product,SalesOrderHeader和SalesOrderDetail。爲了保持重點,咱們使用列的一個子集。blog

AdventureWorks已經正常化了,因此銷售人員信息被分紅三個表格。營業員,員工及聯繫方式。對於一些例子,咱們將把它們看成一個表格。圖1.1顯示了咱們將要使用的一整套表格以及它們之間的關係。

 

圖1.1:將在此階梯中使用的AdventureWorks表

注意:

該樓梯級別顯示的全部TSQL代碼能夠與文章一塊兒下載(請參閱本文底部的連接)

什麼是索引?

咱們以一個簡短的故事開始咱們的索引研究,這個故事使用了一個陳舊的,但已經證明的技術,在咱們介紹索引的基本概念時,咱們將在本文中引用這個故事。

你離開你的房子跑幾個差事。當你回來的時候,你會發現女兒的壘球教練正在等你的消息。特蕾西,麗貝卡和艾米中的三個女孩已經失去了球隊的帽子。你能夠請運動產品商店擺動,併爲女孩買帽子。他們的父母將在下一場比賽中報銷你。 你知道女孩,你知道他們的父母。但你不知道他們的帽子大小。大家鎮的某個地方有三個住宅,每一個住宅都有你須要的信息。沒問題,你只需打電話給父母,並得到帽子大小。您接觸到您的電話,而後到達索引 - 電話號碼簿的白頁。你須要的第一個住所是海倫·邁耶(Helen Meyer)。估計「邁爾」將位於人口中間附近,你跳到白頁的中間,只是發現你在標題爲「Kline-Koerber」的頁面上。你向前跳一小步,到達「Nagle-Nyeong」頁面。一個更小的跳躍,讓你在「馬爾多納多 - 納格爾」頁面。意識到你如今在正確的頁面,你掃描頁面,直到你到達「邁爾,海倫」線,並得到電話號碼。使用電話號碼,您能夠到達Meyer住宅並獲取所需的信息。 你再重複這個過程兩次,到另外兩個住所,再得到兩個帽子尺寸。

您剛剛使用了一個索引,而且已經以與SQL Server使用索引相同的方式使用它;由於白頁和SQL Server索引之間有很大的類似之處和一些區別。

實際上,剛剛使用的索引表明SQL Server支持的兩種SQL Server索引中的一種:聚簇和非聚簇。白頁最能表明非彙集索引的概念。所以,在這個層面上,咱們引入非彙集索引。隨後的級別將引入彙集索引並深刻鑽取這兩種類型。

非彙集索引

白頁相似於非彙集索引,由於它們不是數據自己的組織;而是一種機制或地圖來幫助您訪問這些數據。數據自己就是咱們須要聯繫的實際人員。電話公司沒有按照有意義的順序安排小鎮的住宅,把房子從一個地方搬到另外一個地方,這樣同一個壘球隊的全部女孩就住在一塊兒,房子也沒有居民的姓氏。相反,它會給你一本書,每一個住所都有一個入口。這些條目按照白頁的搜索鍵進行排序;姓氏,名字,中間首字母和街道地址。每一個條目都包含搜索關鍵字和數據,使您可以進入住所;電話號碼。

像白名單中的條目同樣,SQL Server非聚簇索引中的每一個條目都由兩部分組成:

l ·搜索關鍵字,例如姓氏 - 名字 - 中間首字母。 。在SQL Server術語中,這是索引鍵。

l ·書籤與電話號碼具備相同的用途,容許SQL Server直接導航到與此索引條目對應的表中的行。

另外,SQL Server非彙集索引條目具備一些僅供內部使用的頭信息,並可能包含一些可選信息。這兩個都將在後面的層面進行討論。在這個時候,對於非集羣索引的理解也不重要。

像白頁同樣,在搜索關鍵字序列中維護一個SQL Server索引,這樣任何特定的條目均可以經過一組小的「跳轉」來訪問。給定搜索鍵,SQL Server能夠快速到達該鍵的索引條目。與白頁不一樣,SQL Server索引是動態的。也就是說,每次添加,刪除行或者修改了搜索關鍵字列值時,SQL Server都會更新索引。

正如白頁中的條目順序與鎮內住宅的地理順序不同,非彙集索引中的條目順序與表中的行順序不一樣。索引中的第一個條目多是表中最後一行的索引,索引中的第二個條目多是表中第一行的第二個條目。若是事實與索引不一樣,其索引老是有意義的;一個表的行能夠徹底不肯定。

在建立索引時,SQL Server會在基礎表中爲每行生成並維護索引中的一個條目(當咱們覆蓋已過濾的索引時,將在稍後的級別中遇到此常規規則的一個例外)。您能夠在表上建立多個非彙集索引,可是不能有包含來自多個表的數據的索引。

而最大的區別是:SQL Server不能使用電話。它必須使用索引條目的書籤部分中的信息導航到表的相應行。當SQL Server須要任何在數據行中但沒有在相應索引條目中的信息時,這是必要的,例如Tracy Meyer的壘球帽大小。所以,爲了更好的比喻,白頁的條目包含一組GPS座標而不是電話號碼。而後,您使用GPS座標導航到由白頁條目表示的住宅。

建立並受益於非彙集索引

咱們經過兩次查詢咱們的示例數據庫來結束這個級別。確保使用SQL Server 2005專用的AdventureWorks版本,SQL Server 2008可使用該版本。AdventureWorks2008數據庫具備不一樣的表結構,下面的查詢將失敗。咱們將每次運行相同的查詢;可是第一次執行會在咱們建立索引以前發生,第二次執行會在建立索引以後發生。每一次,SQL Server都會告訴咱們在檢索請求的信息方面已經作了多少工做。咱們將在咱們的Contact表中找到「Helen Meyer」行(她的行位於表格中間附近)。最初,該表在「名字」列或「姓氏」列中將不具備索引。爲確保您能夠屢次運行該示例,請確保咱們將在第三批生成的索引不存在,方法是運行如下代碼:

IF EXISTS (SELECT * FROM sys.indexesWHERE OBJECT_ID = OBJECT_ID('Person.Contact')

AND name = 'FullName')DROP INDEX Person.Contact.FullName;

Listing 1.1 - Ensuring the index does not exist

Our task will require four SQL command batches. 

The first command batch:

SET STATISTICS io ON

SET STATISTICS time ONGO

清單1.2 - 打開統計信息

上面的批處理通知SQL Server咱們但願咱們的查詢做爲輸出的一部分返回性能信息。

第二批命令:

SELECT *

    FROM Person.Contact

    WHERE FirstName = 'Helen'

        AND LastName = 'Meyer';GO

清單1.3 - 檢索一些數據

這第二批檢索「海倫邁耶」行:

584 Helen Meyer helen2@adventure-works.com 0-519-555-0112

另外還有如下性能信息:

Table 'Contact'. Scan count 1, logical reads 569. SQL Server Execution Times:   CPU time = 3 ms.

這個輸出告訴咱們,咱們的請求執行了569個邏輯IO,而且須要大約3毫秒的處理器時間來完成。 處理器時間的值可能不一樣。

第三批命令:

CREATE NONCLUSTERED INDEX FullName

            ON Person.Contact

    ( LastName, FirstName );GO

清單1.4 - 建立一個非彙集索引

此批處理在聯繫人表的名字和姓氏列上建立一個非彙集索引。 一個複合索引是一個索引,它有多個列肯定索引行序列。

第四批命令:

SELECT *

    FROM Person.Contact

    WHERE FirstName = 'Helen'

        AND LastName = 'Meyer';GO

清單1.3(再次)

這最後一批是咱們原來的SELECT語句的從新執行。 咱們獲得和之前同樣的返回行; 可是此次的表現統計是不同的

Table 'Contact'. Scan count 1, logical reads 4. SQL Server Execution Times:   CPU time = 0 ms.

這個輸出告訴咱們,咱們的請求只須要4個邏輯IO;而且須要很是少許的處理器時間來檢索「海倫邁耶」行。

結論

建立精心挑選的索引能夠大大提升數據庫性能。在下一個層面,咱們將開始考察索引的物理結構。咱們將研究爲何這個非彙集索引對這個查詢是如此有利,爲何這可能不老是如此。將來的水平將涵蓋其餘類型的指數,指數的額外收益,與指數相關的成本,監測和維護您的指數,以及最佳作法;全部的目標都是爲您提供必要的知識,爲您本身的數據庫中的表建立最佳的索引方案。

可下載的代碼

l Level1 - IntroToIndexes_Durant_Code.sql

l LevelLevel 1 - MillionRowContactTable.sql

 

資源:

Level 1 - IntroToIndexes_Durant_Code.sql | 1級 - MillionRowContactTable.sql

本文是SQL Server索引階梯的一部分

相關文章
相關標籤/搜索