關聯式資料庫的索引技術

2021-08-29 15:11:53 字數 3745 閱讀 1426

摘 要:索引是影響關聯式資料庫(rdbms)效能的重要因素之一。當今常用的關聯式資料庫,如sql server、sybase、oracle、db2等,為了提高效能,都提供相應的索引機制。本文以微軟的sql server資料庫為例,介紹索引的概念、使用方法以及日常維護。

1 索引的概念

索引是乙個單獨的、物理的資料庫結構,它是某個表中一列或若干列值的集合和相應的指向表中物理標識這些值的資料頁的邏輯指標清單。表的儲存由兩部分組成,一部分用來存放資料頁面,另一部分存放索引頁面。通常,索引頁面相對於資料頁面來說小得多。資料檢索花費的大部分開銷是磁碟讀寫,沒有索引就需要從磁碟上讀表的每乙個資料頁,如果有索引,則只需查詢索引頁面就可以了。所以建立合理的索引,就能加速資料的檢索過程。

sql server採用b-樹結構的索引,根據索引的順序與資料表的物理順序是否相同可以分為:聚簇索引(clustered index)和非聚簇索引(nonclustered index)。

(1)聚簇索引重新組織表中的資料以按指定的乙個或多個列的值排序。聚簇索引的葉節點包含實際的資料,因此用它查詢資料很快,但每個表只能建乙個聚簇索引。

(2)非聚簇索引不重新組織表中的資料,它的葉節點中儲存了組成非聚簇索引的列的值和行定位指標。乙個表可以建249 個非聚簇索引。

通俗的說,漢語字典的正文就是乙個建立在拼音基礎上的聚簇索引,以英文本母「a」開頭並以「z」結尾。比如,我們要查「阿」字,就會翻開字典的第一頁,因為「阿」的拼音是「a」,所以排在字典的前面。如果您翻完了所有以「a」開頭的部分仍然找不到這個字,那麼就說明字典中沒有這個字。同樣的,如果查「做」字,就會把字典翻到最後。

字典的「偏旁部首」是非聚簇索引。比如我們要查「阿」字,在查部首之後,看到部首檢字表中「阿」的頁碼是1頁,「阿」的上面是「際」字,但頁碼卻是277頁,「阿」的下面是「隴」字,頁碼是416頁。很顯然,這些字並不是真正的分別位於「阿」字的上下方,現在看到的連續的「際、阿、隴」三字實際上就是他們在非聚簇索引中的排序,是字典正文中的字在非聚簇索引中的對映。

2 索引的使用

1)聚簇索引的使用

在聚簇索引下,資料在物理上按順序排在資料頁上,重複值也排在一起,因而在那些包含範圍檢查(between、<、<=、& gt;、>=)或使用group by、order by的查詢時,一旦找到具有範圍中第乙個鍵值的行,具有後續索引值的行必然連在一起,不必進一步搜尋,避免了大範圍掃瞄,可以大大提高查詢速度。

聚簇索引的侯選列是:

u 經常按範圍訪問的列,如date>」20050101」 and date< 「20050131」;

u 經常在where子句中使用並且插入是隨機的主鍵列;

u 在group by或order by中使用的列;

u 在連線操作中使用的列。

2)非聚簇索引的使用

由於非聚簇索引的葉級點不包含實際的資料,因此它檢索效率較低,但乙個表只能建乙個聚簇索引,當使用者需要建立多個索引時就需要使用非聚簇索引了。在建立非聚簇索引時,要權衡索引對查詢速度的加快與降低修改速度之間的利弊。

在下面情況中使用非聚簇索引:

u 常用於集合函式(如sum,....)的列;

u 常用於join, order by, group by的列;

u 查尋出的資料不超過表中資料量的20%。

表1 索引使用情況分析表

情況描述 使用聚簇索引 使用非聚簇索引

用於返回某範圍內資料的列 應 不應

經常被用作分組排序的列 應 應

小數目不同值的列 應 不應

連線操作使用的列 應 應

頻繁更新、修改的列 不應 應

乙個或極少不同值的列 不應 不應

大數目不同值的列 不應 應

3)建立索引需要注意的要點

1) 慎重選擇作為聚簇索引的列

預設情況下,sql server用主鍵建立聚簇索引。這種做法常常造成聚簇索引的浪費。通常,我們會為每個表建立乙個id列,以區分每條資料,並且該列是自動增大的,步長一般為1。如果我們把這個列設為主鍵,sql server會將此列缺省為聚簇索引。這樣做可以使資料在資料庫中按id進行物理排序,但這種做法在實際應用中意義並不大。根據前面談到的聚簇索引的定義和使用情況可以看出,使用聚簇索引的最大好處就是能夠根據查詢要求,迅速返回某個範圍內的資料,避免全表掃瞄。在實際應用中,因為id號是自動生成的,我們並不知道每條記錄的id號,所以我們不太可能用id號來進行查詢。這就使聚簇索引成為擺設,造成資源浪費。其次,讓每個值都不同的id列作為聚簇索引也不符合「大數目的不同值情況下不應建立聚簇索引」規則。

一般情況下,資料庫應用系統進行資料檢索都離不開「 使用者名稱(**)」、「日期」字段。以筆者所用的his系統(醫院管理資訊系統)為例,我們進行費用、處方、檢查單等資訊檢索時需要根據「住院號」和「日期 」這兩個欄位來返回特定範圍內的資料。下面我們分幾種情況觀察在不同索引條件下查詢相同內容所用的時間。

假設病人費用表名為「brfy」,其中住院號欄位名為「zyh」,日期欄位名為「riqi」,要求是從表brfy中檢索zyh為「028246」的病人2023年3月1日到20日的費用,對應的sql語句如下:

select * from brfy where zyh=』028246』 and riqi>=』20050301』 and riqi<=』20050320』;

第一種情況,用id列建立聚簇索引,不為zyh和riqi建立索引,查詢時間為87秒。

第二種情況,用id列建立聚簇索引,為zyh和riqi兩列建立非聚簇索引(zyh在前),查詢時間為33秒。

第三種情況,用zyh和riqi兩列建立聚簇索引(zyh在前),查詢時間為2秒。

由以上分析可以看出聚簇索引是非常寶貴的,應該為經常用於檢索某個範圍內資料的列或group by、order by等子句的列建立聚簇索引,這樣能夠極大的提高系統效能。

2) 重視以多個列建立的索引中列的順序問題

一些使用者認為只要合理的選擇列建立索引,不必關心列的順序就可以提高檢索速度,這種觀點是錯誤的。多列索引中列的先後順序應該和實際應用中 where、group by或order by等子句里列的放置位置相同。參考上面舉的例子,在第

二、第三種情況下,如果把riqi放在zyh前面,執行上述sql語句就不會用到這兩個索引,檢索的時間也會變得很長。

3 索引的維護

資料庫系統執行一段時間後,隨著資料行的插入、刪除和資料頁的**,索引對系統的優化效能就會大大降低。這時候,我們需要對索引進行分析和重建。

sql server使用dbcc showcontig確定是否需要重建表的索引。在 sql server的查詢分析器中輸入命令:

use database_name

declare @table_id int

set @table_id=object_id ('employee')

dbcc showcontig (@table_id)

在命令返回的引數中scan density 是索引效能的關鍵指示器,這個值越接近100%越好,一般在低於90%的情況下,就需要重建索引。重建索引可以使用dbcc dbreindex,使用方式如下:

dbcc dbreindex('表名', 索引名, 填充因子) /*填充因子一般為90或100*/

如果重建後,scan density還沒有達到100%,可以重建該錶的所有索引:

dbcc dbreindex('表名', '', 填充因子)

在良好的資料庫設計基礎上,有效地使用索引是資料庫應用系統取得高效能的基礎。然而,任何事物都具有兩面性,索引也不例外。索引的建立需要占用額外的儲存空間,並且在增、刪、改操作中也會增加一定的工作量,因此,在適當的地方增加適當的索引並從不合理的地方刪除次要的索引,將有助於優化那些效能較差的資料庫應用系統。實踐表明,合理的索引設計是建立在對各種查詢的分析和**上的,只有正確地使索引與程式結合起來,才能產生最佳的優化方案

關聯式資料庫與非關聯式資料庫

關係型資料庫,是指採用了關係模型來組織資料的資料庫。關係模型是在1970年由ibm的研究員e.f.codd博士首先提出的,在之後的幾十年中,關係模型的概念得到了充分的發展並逐漸成為主流資料庫結構的主流模型。簡單來說,關係模型指的就是二維 模型,而乙個關係型資料庫就是由二維表及其之間的聯絡所組成的乙個...

關聯式資料庫與非關聯式資料庫

關係型資料庫,是指採用了關係模型來組織資料的資料庫。關係模型是在1970年由ibm的研究員e.f.codd博士首先提出的,在之後的幾十年中,關係模型的概念得到了充分的發展並逐漸成為主流資料庫結構的主流模型。簡單來說,關係模型指的就是二維 模型,而乙個關係型資料庫就是由二維表及其之間的聯絡所組成的乙個...

mysql關聯式資料庫 關聯式資料庫概述

為什麼需要資料庫?因為應用程式需要儲存使用者的資料,比如word需要把使用者文件儲存起來,以便下次繼續編輯或者拷貝到另一台電腦。要儲存使用者的資料,乙個最簡單的方法是把使用者資料寫入檔案。例如,要儲存乙個班級所有學生的資訊,可以向檔案中寫入乙個csv檔案 id,name,gender,score 1...