數據庫索引實例

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

表或視圖能夠包含如下類型的索引:

* 彙集
o 彙集索引根據數據行的鍵值在表或視圖中排序和存儲這些數據行。索引定義中包含彙集索引列。每一個表只能有一個彙集索引,由於數據行自己只能按一個順序排序。
o 只有當表包含彙集索引時,表中的數據行才按排序順序存儲。若是表具備彙集索引,則該表稱爲彙集表。若是表沒有彙集索引,則其數據行存儲在一個稱爲堆的無序結構中。
* 非彙集
o 非彙集索引具備獨立於數據行的結構。非彙集索引包含非彙集索引鍵值,而且每一個鍵值項都有指向包含該鍵值的數據行的指針
o 從非彙集索引中的索引行指向數據行的指針稱爲行定位器。行定位器的結構取決於數據頁是存儲在堆中仍是彙集表中。對於堆,行定位器是指向行的指針。對於彙集表,行定位器是彙集索引鍵。
o 您能夠向非彙集索引的葉級添加非鍵列以跳過現有的索引鍵限制(900 字節和 16 鍵列),並執行完整範圍內的索引查詢。

彙集索引和非彙集索引均可以是惟一的。這意味着任何兩行都不能有相同的索引鍵值。另外,索引也能夠不是惟一的,即多行能夠共享同一鍵值。

每當修改了表數據後,都會自動維護表或視圖的索引。

索引和約束

對錶列定義了 PRIMARY KEY 約束和 UNIQUE 約束時,會自動建立索引。例如,若是建立了表並將一個特定列標識爲主鍵,則 數據庫引擎自動對該列建立 PRIMARY KEY 約束和索引。有關詳細信息,請參閱建立索引(數據庫引擎)。

2、索引有什麼用

與書中的索引同樣,數據庫中的索引使您能夠快速找到表或索引視圖中的特定信息。索引包含從表或視圖中一個或多個列生成的鍵,以及映射到指定數據的存儲位置的指針。經過建立設計良好的索引以支持查詢,能夠顯著提升數據庫查詢和應用程序的性能。索引能夠減小爲返回查詢結果集而必須讀取的數據量。索引還能夠強制表中的行具備惟一性,從而確保表數據的數據完整性

設計良好的索引能夠減小磁盤 I/O 操做,而且消耗的系統資源也較少,從而能夠提升查詢性能。對於包含 SELECT、UPDATE、DELETE 或 MERGE 語句的各類查詢,索引會頗有用。例如,在 AdventureWorks 數據庫中執行的查詢 SELECT Title, HireDate FROM HumanResources.Employee WHERE EmployeeID = 250。執行此查詢時,查詢優化器評估可用於檢索數據的每一個方法,而後選擇最有效的方法。可能採用的方法包括掃描表和掃描一個或多個索引(若是有)。

掃描表時,查詢優化器讀取表中的全部行,並提取知足查詢條件的行。掃描表會有許多磁盤 I/O 操做,並佔用大量資源。可是,若是查詢的結果集是佔表中較高百分比的行,掃描表會是最爲有效的方法。

查詢優化器使用索引時,搜索索引鍵列,查找到查詢所需行的存儲位置,而後從該位置提取匹配行。一般,搜索索引比搜索表要快不少,由於索引與表不一樣,通常每行包含的列很是少,且行遵循排序順序。

查詢優化器在執行查詢時一般會選擇最有效的方法。但若是沒有索引,則查詢優化器必須掃描表。您的任務是設計並建立最適合您的環境的索引,以便查詢優化器能夠從多個有效的索引中選擇。SQL Server 提供的數據庫引擎優化顧問能夠幫助分析數據庫環境並選擇適當的索引。

3、索引怎麼用

索引其實關鍵目的是爲了加快檢索速度而創建的,因此,怎麼用索引是數據庫系統自己的事情,做爲數據庫設計或使用者,設計並建立好索引而後體驗加上索引後的查詢變快的感受就好了。因此,索引怎麼用就變爲了「怎麼建立合適的索引」,如下說明這個問題:

索引設計不佳和缺乏索引是提升數據庫和應用程序性能的主要障礙。設計高效的索引對於得到良好的數據庫和應用程序性能極爲重要。爲數據庫及其工做負荷選擇正確的索引是一項須要在查詢速度與更新所需開銷之間取得平衡的複雜任務。若是索引較窄,或者說索引關鍵字中只有不多的幾列,則須要的磁盤空間和維護開銷都較少。而另外一方面,寬索引可覆蓋更多的查詢。您可能須要試驗若干不一樣的設計,才能找到最有效的索引。能夠添加、修改和刪除索引而不影響數據庫架構或應用程序設計。所以,應試驗多個不一樣的索引而無需猶豫。

SQL Server 中的查詢優化器可在大多數狀況下可靠地選擇最高效的索引。整體索引設計策略應爲查詢優化器提供可供選擇的多個索引,並依賴查詢優化器作出正確的決定。這在多種狀況下可減小分析時間並得到良好的性能。若要查看查詢優化器對特定查詢使用的索引,請在 SQL Server Management Studio 中的「查詢」菜單上選擇「包括實際的執行計劃」。

不要老是將索引的使用等同於良好的性能,或者將良好的性能等同於索引的高效使用。若是隻要使用索引就能得到最佳性能,那查詢優化器的工做就簡單了。但事實上,不正確的索引選擇並不能得到最佳性能。所以,查詢優化器的任務是隻在索引或索引組合能提升性能時才選擇它,而在索引檢索有礙性能時則避免使用它。

建議的索引設計策略包括如下任務:

1. 瞭解數據庫自己的特徵。例如,它是頻繁修改數據的聯機事務處理 (OLTP) 數據庫,仍是主要包含只讀數據的決策支持系統 (DSS) 或數據倉庫 (OLAP) 數據庫?
2. 瞭解最經常使用的查詢的特徵。例如,瞭解到最經常使用的查詢聯接兩個或多個表將有助於決定要使用的最佳索引類型。
3. 瞭解查詢中使用的列的特徵。例如,某個索引對於含有整數數據類型同時仍是惟一的或非空的列是理想索引。篩選索引適用於具備定義完善的數據子集的列。
4. 肯定哪些索引選項可在建立或維護索引時提升性能。例如,對現有某個大型表建立彙集索引將會受益於 ONLINE 索引選項。ONLINE 選項容許在建立索引或從新生成索引時繼續對基礎數據執行併發活動。
5. 肯定索引的最佳存儲位置。非彙集索引能夠與基礎表存儲在同一個文件組中,也能夠存儲在不一樣的文件組中。索引的存儲位置可經過提升磁盤 I/O 性能來提升查詢性能。例如,將非彙集索引存儲在表文件組所在磁盤之外的某個磁盤上的一個文件組中能夠提升性能,由於能夠同時讀取多個磁盤。
或者,彙集索引和非彙集索引也可使用跨越多個文件組的分區方案。在維護整個集合的完整性時,使用分區能夠快速而有效地訪問或管理數據子集,從而使大型表或索引更易於管理。有關詳細信息,請參閱已分區表和已分區索引。在考慮分區時,應肯定是否應對齊索引,即,是按實質上與表相同的方式進行分區,仍是單獨分區。

# 設計索引。
索引設計是一項關鍵任務。索引設計包括肯定要使用的列,選擇索引類型(例如彙集或非彙集),選擇適當的索引選項,以及肯定文件組或分區方案佈置。

# 肯定最佳的建立方法。按照如下方法建立索引:

* 使用 CREATE TABLE 或 ALTER TABLE 對列定義 PRIMARY KEY 或 UNIQUE 約束
SQL Server 數據庫引擎自動建立惟一索引來強制 PRIMARY KEY 或 UNIQUE 約束的惟一性要求。默認狀況下,建立的惟一彙集索引能夠強制 PRIMARY KEY 約束,除非表中已存在彙集索引或指定了惟一的非彙集索引。默認狀況下,建立的惟一非彙集索引能夠強制 UNIQUE 約束,除非已明確指定惟一的彙集索引且表中不存在彙集索引。
還能夠指定索引選項和索引位置、文件組或分區方案。
建立爲 PRIMARY KEY 或 UNIQUE 約束的一部分的索引將自動給定與約束名稱相同的名稱。

* 使用 CREATE INDEX 語句或 SQL Server Management Studio 對象資源管理器中的「新建索引」對話框建立獨立於約束的索引
必須指定索引的名稱、表以及應用該索引的列。還能夠指定索引選項和索引位置、文件組或分區方案。默認狀況下,若是未指定彙集或惟一選項,將建立非彙集的非惟一索引。若要建立篩選索引,請使用可選的 WHERE 子句。

# 建立索引。
要考慮的一個重要因素是對空表仍是對包含數據的表建立索引。對空表建立索引在建立索引時不會對性能產生任何影響,而向表中添加數據時,會對性能產生影響。
對大型表建立索引時應仔細計劃,這樣纔不會影響數據庫性能。對大型表建立索引的首選方法是先建立彙集索引,而後建立任何非彙集索引。在對現有表建立索引時,請考慮將 ONLINE 選項設置爲 ON。該選項設置爲 ON 時,將不持有長期表鎖以繼續對基礎表的查詢或更新。

簡單的建立索引,可採用以下語句:
CREATE INDEX IX_ProductVendor_VendorID
ON Purchasing.ProductVendor (VendorID, VendorName);
GOsql

索引用於快速找出在某個列中有一特定值的行。不使用索引,MySQL必須從第1條記錄開始而後讀完整個表直到找出相關的行。數據庫

表越大,花費的時間越多。若是表中查詢的列有一個索引,MySQL能快速到達一個位置去搜尋到數據文件的中間,沒有必要看全部數據。架構

大多數MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)在B樹中存儲。只是空間列類型的索引使用R-樹,而且MEMORY表還支持hash索引併發

大多數狀況下索引能大幅度提升查詢效率,但:數據庫設計

  • 數據的變動(增刪改)都須要維護索引,所以更多的索引意味着更多的維護成本
  • 更多的索引意味着也須要更多的空間 (一本100頁的書,卻有50頁目錄?)
  • 太小的表,建索引可能會更慢哦 :) (讀個2頁的宣傳手冊,你還先去找目錄?)

索引的字段類型問題

  • text類型,也可建索引(需指定長度)
  • myisam存儲引擎索引鍵長度綜合不能超過1000字節
  • 用來篩選的值儘可能保持和索引列一樣的數據類型

like 不能用索引?

  • 儘可能減小like,但不是絕對不可用,」xxxx%」 是能夠用到索引的,函數

    想象一下,你在看一本成語詞典,目錄是按成語拼音順序創建,查詢需求是,你想找以 「一」字開頭的成語(」一%「),和你想找包含一字的成語(「%一%」)工具

  • 除了like,如下操做符也可用到索引:性能

    <,<=,=,>,>=,BETWEEN,IN測試

    <>,not in ,!=則不行優化

什麼樣的字段不適合建索引?

通常來講,列的值惟一性過小(如性別,類型什麼的),不適合建索引(怎樣叫過小?一半說來,同值的數據超過表的百分之15,那就不必建索引了) 
太長的列,能夠選擇只創建部分索引,(如:只取前十位作索引) 
更新很是頻繁的數據不適宜建索引(怎樣叫很是?意會)

一次查詢能用多個索引嗎?

不能

多列查詢該如何建索引?

一次查詢只能用到一個索引,因此 首先槍斃 a,b各建索引方案

a仍是b? 誰的區分度更高(同值的最少),建誰!

固然,聯合索引也是個不錯的方案,ab,仍是ba,則同上,區分度高者,在前

聯合索引的問題?

where a = 「xxx」 可使用 AB 聯合索引 
where b = 「xxx」 則不可 (再想象一下,這是書的目錄?)

因此,大多數狀況下,有AB索引了,就能夠不用在去建一個A索引了

哪些常見狀況不能用索引?

like 「%xxx」 
not in , != 
對列進行函數運算的狀況(如 where md5(password) = 「xxxx」) 
WHERE index=1 OR A=10 
存了數值的字符串類型字段(如手機號),查詢時記得不要丟掉值的引號,不然沒法用到該字段相關索引,反之則不要緊 
也即

select * from test where mobile = 13711112222;

但是沒法用到mobile字段的索引的哦(若是mobile是char 或 varchar類型的話)

btw,千萬不要嘗試用int來存手機號(爲何?本身想!要不本身試試)

覆蓋索引(Covering Indexes)擁有更高效率

索引包含了所需的所有值的話,就只select 他們,換言之,只select 須要用到的字段,如無必要,可儘可能避免select *

NULL 的問題

NULL會致使索引形同虛設,因此在設計表結構時應避免NULL 的存在(用其餘方式表達你想表達的NULL,好比 -1?)

如何查看索引信息,如何分析是否正確用到索引?

show index from tablename; 
explain select ……;

1.建立表並插入數據

在Sql Server2008中建立測試數據庫Test,接着建立數據庫表並插入數據,sql代碼以下:

複製代碼
USE Test
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES 
      WHERE TABLE_NAME = 'emp_pay')
   DROP TABLE emp_pay
GO
USE Test
IF EXISTS (SELECT name FROM sys.indexes 
      WHERE name = 'employeeID_ind')
   DROP INDEX emp_pay.employeeID_ind
GO
USE Test
GO
CREATE TABLE emp_pay
(
 employeeID int NOT NULL,
 base_pay money NOT NULL,
 commission decimal(2, 2) NOT NULL
)
INSERT emp_pay
   VALUES (1, 500, .10)
INSERT emp_pay 
   VALUES (2, 1000, .05)
INSERT emp_pay 
   VALUES (6, 800, .07)
INSERT emp_pay
   VALUES (5, 1500, .03)
INSERT emp_pay
   VALUES (9, 750, .06)
複製代碼

執行完上述sql代碼之後咱們會發如今Test數據庫中多出了一張emp_pay表,數據庫表的內容以下圖所示:

2.無索引查找

從上圖咱們能夠看出數據庫中存儲的數據排列順序與咱們插入的前後順序一致。接下來咱們查詢employeeID=5的字段,執行以下sql代碼:

USE Test
SELECT * FROM emp_pay where employeeID=5

在SQL SERVER MANAGEMENT STUDIO中咱們點擊「顯示估計的查詢計劃」,會出現以下圖所示的查詢計劃圖:

其中表掃描的內容爲:

3.建立索引

接下來咱們爲上述表添加彙集惟一索引,代碼以下:

SET NOCOUNT OFF
CREATE UNIQUE CLUSTERED INDEX employeeID_ind
   ON emp_pay (employeeID)
GO

在執行完上述建立索引的代碼之後,咱們再次查詢emp_pay的數據內容,以下圖所示:

從上圖咱們能夠發現數據內容已經按照employeeID進行了排序。

咱們繼續執行前面關於employeeID=5的查詢,點擊「顯示估計的執行計劃」,出現以下圖所示內容:

彙集索引查找的內容爲:

總結:

當咱們爲數據庫表中的某一個字段建立索引,而且在查詢語句中where子句中用到這樣一個字段,那麼查詢效率會有所提升,咱們上述實驗由於數據量的關係查詢效率提升不明顯。

補充

咱們上面添加的索引是惟一彙集索引,所以當插入的數據在employeeID字段出現重複時會報錯。假如咱們在建立索引以前數據字段出現重複,那麼就不能建立惟一索引。

建立索引之後的排序(PS:2012-5-28)

執行以下sql語句

update emp_pay set employeeID=7 where employeeID=1;

而後再次執行全表查詢,咱們發現查詢結果以下所示:

只要咱們更新了employeeID,那麼最後的更新結果都會按照employeeID的值進行升序排序。這是由於咱們在employeeID上建立了索引的緣故。

刪除索引(PS:2012-6-4)

咱們能夠經過sql server management studio這個工具刪除索引,也能夠經過sql語句進行索引的刪除,假設咱們要求刪除在前面建立的索引employeeID_ind,那麼sql語句以下代碼所示:

DROP INDEX employeeID_ind ON emp_pay;    
相關文章
相關標籤/搜索