使用資料庫索引
MySQL支持很多數據類型,選擇合適的數據類型存儲數據對性能有很大的影響。通常來說,可以遵循以下一些指導原則:
(1)越小的數據類型通常更好:越小的數據類型通常在磁碟、內存和CPU緩存中都需要更少的空間,處理起來更快。
(2)簡單的數據類型更好:整型數據比起字元,處理開銷更小,因為字元串的比較更復雜。在MySQL中,應該用內置的日期和時間數據類型,而不是用字元串來存儲時間;以及用整型數據類型存儲IP地址。
(3)盡量避免NULL:應該指定列為NOT NULL,除非你想存儲NULL。在MySQL中,含有空值的列很難進行查詢優化,因為它們使得索引、索引的統計信息以及比較運算更加復雜。你應該用0、一個特殊的值或者一個空串代替空值。
❷ 資料庫建立索引怎麼利用索引查詢
1.合理使用索引
索引是資料庫中重要的數據結構,它的根本目的就是為了提高查詢效率。現在大多數的資料庫產品都採用IBM最先提出的ISAM索引結構。
索引的使用要恰到好處,其使用原則如下:
在經常進行連接,但是沒有指定為外鍵的列上建立索引,而不經常連接的欄位則由優化器自動生成索引。
在頻繁進行排序或分組(即進行group by或order by操作)的列上建立索引。
在條件表達式中經常用到的不同值較多的列上建立檢索,在不同值少的列上不要建立索引。比如在雇員表的「性別」列上只有「男」與「女」兩個不同值,因此就無必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度。
如果待排序的列有多個,可以在這些列上建立復合索引(compound index)。
使用系統工具。如Informix資料庫有一個tbcheck工具,可以在可疑的索引上進行檢查。在一些資料庫伺服器上,索引可能失效或者因為頻繁操作而 使得讀取效率降低,如果一個使用索引的查詢不明不白地慢下來,可以試著用tbcheck工具檢查索引的完整性,必要時進行修復。另外,當資料庫表更新大量 數據後,刪除並重建索引可以提高查詢速度。
(1)在下面兩條select語句中:
SELECT * FROM table1 WHERE field1<=10000 AND field1>=0;
SELECT * FROM table1 WHERE field1>=0 AND field1<=10000;
如果數據表中的數據field1都>=0,則第一條select語句要比第二條select語句效率高的多,因為第二條select語句的第一個條件耗費了大量的系統資源。
第一個原則:在where子句中應把最具限制性的條件放在最前面。
(2)在下面的select語句中:
SELECT * FROM tab WHERE a=… AND b=… AND c=…;
若有索引index(a,b,c),則where子句中欄位的順序應和索引中欄位順序一致。
第二個原則:where子句中欄位的順序應和索引中欄位順序一致。
——————————————————————————
以下假設在field1上有唯一索引I1,在field2上有非唯一索引I2。
——————————————————————————
(3) SELECT field3,field4 FROM tb WHERE field1='sdf' 快
SELECT * FROM tb WHERE field1='sdf' 慢[/cci]
因為後者在索引掃描後要多一步ROWID表訪問。
(4) SELECT field3,field4 FROM tb WHERE field1>='sdf' 快
SELECT field3,field4 FROM tb WHERE field1>'sdf' 慢
因為前者可以迅速定位索引。
(5) SELECT field3,field4 FROM tb WHERE field2 LIKE 'R%' 快
SELECT field3,field4 FROM tb WHERE field2 LIKE '%R' 慢,
因為後者不使用索引。
(6) 使用函數如:
SELECT field3,field4 FROM tb WHERE upper(field2)='RMN'不使用索引。
如果一個表有兩萬條記錄,建議不使用函數;如果一個表有五萬條以上記錄,嚴格禁止使用函數!兩萬條記錄以下沒有限制。
(7) 空值不在索引中存儲,所以
SELECT field3,field4 FROM tb WHERE field2 IS[NOT] NULL不使用索引。
(8) 不等式如
SELECT field3,field4 FROM tb WHERE field2!='TOM'不使用索引。
相似地,
SELECT field3,field4 FROM tb WHERE field2 NOT IN('M','P')不使用索引。
(9) 多列索引,只有當查詢中索引首列被用於條件時,索引才能被使用。
(10) MAX,MIN等函數,使用索引。
SELECT max(field2) FROM tb 所以,如果需要對欄位取max,min,sum等,應該加索引。
一次只使用一個聚集函數,如:
SELECT 「min」=min(field1), 「max」=max(field1) FROM tb
不如:SELECT 「min」=(SELECT min(field1) FROM tb) , 「max」=(SELECT max(field1) FROM tb)
(11) 重復值過多的索引不會被查詢優化器使用。而且因為建了索引,修改該欄位值時還要修改索引,所以更新該欄位的操作比沒有索引更慢。
(12) 索引值過大(如在一個char(40)的欄位上建索引),會造成大量的I/O開銷(甚至會超過表掃描的I/O開銷)。因此,盡量使用整數索引。 Sp_estspace可以計算表和索引的開銷。
(13) 對於多列索引,ORDER BY的順序必須和索引的欄位順序一致。
(14) 在sybase中,如果ORDER BY的欄位組成一個簇索引,那麼無須做ORDER BY。記錄的排列順序是與簇索引一致的。
(15) 多表聯結(具體查詢方案需要通過測試得到)
where子句中限定條件盡量使用相關聯的欄位,且盡量把相關聯的欄位放在前面。
SELECT a.field1,b.field2 FROM a,b WHERE a.field3=b.field3
field3上沒有索引的情況下:
對a作全表掃描,結果排序
對b作全表掃描,結果排序
結果合並。
對於很小的表或巨大的表比較合適。
field3上有索引
按照表聯結的次序,b為驅動表,a為被驅動表
對b作全表掃描
對a作索引范圍掃描
如果匹配,通過a的rowid訪問
(16) 避免一對多的join。如:
SELECT tb1.field3,tb1.field4,tb2.field2 FROM tb1,tb2 WHERE tb1.field2=tb2.field2 AND tb1.field2=『BU1032』 AND tb2.field2= 『aaa』
不如:
declare @a varchar(80)
SELECT @a=field2 FROM tb2 WHERE field2=『aaa』
SELECT tb1.field3,tb1.field4,@a FROM tb1 WHERE field2= 『aaa』
(16) 子查詢
用exists/not exists代替in/not in操作
比較:
SELECT a.field1 FROM a WHERE a.field2 IN(SELECT b.field1 FROM b WHERE b.field2=100)
SELECT a.field1 FROM a WHERE EXISTS( SELECT 1 FROM b WHERE a.field2=b.field1 AND b.field2=100)
SELECT field1 FROM a WHERE field1 NOT IN( SELECT field2 FROM b)
SELECT field1 FROM a WHERE NOT EXISTS( SELECT 1 FROM b WHERE b.field2=a.field1)
(17) 主、外鍵主要用於數據約束,sybase中創建主鍵時會自動創建索引,外鍵與索引無關,提高性能必須再建索引。
(18) char類型的欄位不建索引比int類型的欄位不建索引更糟糕。建索引後性能只稍差一點。
(19) 使用count(*)而不要使用count(column_name),避免使用count(DISTINCT column_name)。
(20) 等號右邊盡量不要使用欄位名,如:
SELECT * FROM tb WHERE field1 = field3
(21) 避免使用or條件,因為or不使用索引。
2.避免使用order by和group by字句。
因為使用這兩個子句會佔用大量的臨時空間(tempspace),如果一定要使用,可用視圖、人工生成臨時表的方法來代替。
如果必須使用,先檢查memory、tempdb的大小。
測試證明,特別要避免一個查詢里既使用join又使用group by,速度會非常慢!
3.盡量少用子查詢,特別是相關子查詢。因為這樣會導致效率下降。
一個列的標簽同時在主查詢和where子句中的查詢中出現,那麼很可能當主查詢中的列值改變之後,子查詢必須重新查詢一次。查詢嵌套層次越多,效率越低,因此應當盡量避免子查詢。如果子查詢不可避免,那麼要在子查詢中過濾掉盡可能多的行。
4.消除對大型錶行數據的順序存取
在 嵌套查詢中,對表的順序存取對查詢效率可能產生致命的影響。
比如採用順序存取策略,一個嵌套3層的查詢,如果每層都查詢1000行,那麼這個查詢就要查詢 10億行數據。
避免這種情況的主要方法就是對連接的列進行索引。
例如,兩個表:學生表(學號、姓名、年齡……)和選課表(學號、課程號、成績)。如果兩個 表要做連接,就要在「學號」這個連接欄位上建立索引。
還可以使用並集來避免順序存取。盡管在所有的檢查列上都有索引,但某些形式的where子句強迫優化器使用順序存取。
下面的查詢將強迫對orders表執行順序操作:
SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008
雖然在customer_num和order_num上建有索引,但是在上面的語句中優化器還是使用順序存取路徑掃描整個表。因為這個語句要檢索的是分離的行的集合,所以應該改為如下語句:
SELECT * FROM orders WHERE customer_num=104 AND order_num>1001
UNION
SELECT * FROM orders WHERE order_num=1008
這樣就能利用索引路徑處理查詢。
5.避免困難的正規表達式
MATCHES和LIKE關鍵字支持通配符匹配,技術上叫正規表達式。但這種匹配特別耗費時間。例如:SELECT * FROM customer WHERE zipcode LIKE 「98_ _ _」
即使在zipcode欄位上建立了索引,在這種情況下也還是採用順序掃描的方式。如果把語句改為SELECT * FROM customer WHERE zipcode >「98000」,在執行查詢時就會利用索引來查詢,顯然會大大提高速度。
另外,還要避免非開始的子串。例如語句:SELECT * FROM customer WHERE zipcode[2,3] >「80」,在where子句中採用了非開始子串,因而這個語句也不會使用索引。
6.使用臨時表加速查詢
把表的一個子集進行排序並創建臨時表,有時能加速查詢。它有助於避免多重排序操作,而且在其他方面還能簡化優化器的工作。例如:
SELECT cust.name,rcvbles.balance,……other COLUMNS
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
AND cust.postcode>「98000」
ORDER BY cust.name
如果這個查詢要被執行多次而不止一次,可以把所有未付款的客戶找出來放在一個臨時文件中,並按客戶的名字進行排序:
SELECT cust.name,rcvbles.balance,……other COLUMNS
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>;0
ORDER BY cust.name
INTO TEMP cust_with_balance
然後以下面的方式在臨時表中查詢:
SELECT * FROM cust_with_balance
WHERE postcode>「98000」
臨時表中的行要比主表中的行少,而且物理順序就是所要求的順序,減少了磁碟I/O,所以查詢工作量可以得到大幅減少。
注意:臨時表創建後不會反映主表的修改。在主表中數據頻繁修改的情況下,注意不要丟失數據。
7.用排序來取代非順序存取
非順序磁碟存取是最慢的操作,表現在磁碟存取臂的來回移動。SQL語句隱藏了這一情況,使得我們在寫應用程序時很容易寫出要求存取大量非順序頁的查詢。
❸ 關於資料庫中的索引使用,以下哪些說法是正確的
A 不對,引用的這一列必須出現在最左側,否則所以失效
B對
C對
D錯,說的太絕對了
實際上在某些情況下,使用全表掃描比使用索引掃描能更快的得到數據結果。
❹ 如何正確使用資料庫索引
問題補充:能不能具體點,新建一個索引就可以了嗎
基本上可以這么說,不過你也可以修改索引。
記住:
索引其實關鍵目的是為了加快檢索速度而建立的,所以,怎麼用索引是資料庫系統本身的事情,作為資料庫設計或使用者,設計並創建好索引然後體驗加上索引後的查詢變快的感覺就行了。所以,索引怎麼用就變為了「怎麼創建合適的索引」
以下回答是否符合你的要求?你還有什麼問題?
第一次回答:
一、索引是什麼
索引是與表或視圖關聯的磁碟上結構,可以加快從表或視圖中檢索行的速度。索引包含由表或視圖中的一列或多列生成的鍵。這些鍵存儲在一個結構(B 樹)中,使 SQL Server 可以快速有效地查找與鍵值關聯的行。
表或視圖可以包含以下類型的索引:
* 聚集
o 聚集索引根據數據行的鍵值在表或視圖中排序和存儲這些數據行。索引定義中包含聚集索引列。每個表只能有一個聚集索引,因為數據行本身只能按一個順序排序。
o 只有當表包含聚集索引時,表中的數據行才按排序順序存儲。如果表具有聚集索引,則該表稱為聚集表。如果表沒有聚集索引,則其數據行存儲在一個稱為堆的無序結構中。
* 非聚集
o 非聚集索引具有獨立於數據行的結構。非聚集索引包含非聚集索引鍵值,並且每個鍵值項都有指向包含該鍵值的數據行的指針。
o 從非聚集索引中的索引行指向數據行的指針稱為行定位器。行定位器的結構取決於數據頁是存儲在堆中還是聚集表中。對於堆,行定位器是指向行的指針。對於聚集表,行定位器是聚集索引鍵。
o 您可以向非聚集索引的葉級添加非鍵列以跳過現有的索引鍵限制(900 位元組和 16 鍵列),並執行完整范圍內的索引查詢。
聚集索引和非聚集索引都可以是唯一的。這意味著任何兩行都不能有相同的索引鍵值。另外,索引也可以不是唯一的,即多行可以共享同一鍵值。
每當修改了表數據後,都會自動維護表或視圖的索引。
索引和約束
對表列定義了 PRIMARY KEY 約束和 UNIQUE 約束時,會自動創建索引。例如,如果創建了表並將一個特定列標識為主鍵,則 資料庫引擎自動對該列創建 PRIMARY KEY 約束和索引。有關詳細信息,請參閱創建索引(資料庫引擎)。
二、索引有什麼用
與書中的索引一樣,資料庫中的索引使您可以快速找到表或索引視圖中的特定信息。索引包含從表或視圖中一個或多個列生成的鍵,以及映射到指定數據的存儲位置的指針。通過創建設計良好的索引以支持查詢,可以顯著提高資料庫查詢和應用程序的性能。索引可以減少為返回查詢結果集而必須讀取的數據量。索引還可以強製表中的行具有唯一性,從而確保表數據的數據完整性。
設計良好的索引可以減少磁碟 I/O 操作,並且消耗的系統資源也較少,從而可以提高查詢性能。對於包含 SELECT、UPDATE、DELETE 或 MERGE 語句的各種查詢,索引會很有用。例如,在 AdventureWorks 資料庫中執行的查詢 SELECT Title, HireDate FROM HumanResources.Employee WHERE EmployeeID = 250。執行此查詢時,查詢優化器評估可用於檢索數據的每個方法,然後選擇最有效的方法。可能採用的方法包括掃描表和掃描一個或多個索引(如果有)。
掃描表時,查詢優化器讀取表中的所有行,並提取滿足查詢條件的行。掃描表會有許多磁碟 I/O 操作,並佔用大量資源。但是,如果查詢的結果集是占表中較高百分比的行,掃描表會是最為有效的方法。
查詢優化器使用索引時,搜索索引鍵列,查找到查詢所需行的存儲位置,然後從該位置提取匹配行。通常,搜索索引比搜索表要快很多,因為索引與表不同,一般每行包含的列非常少,且行遵循排序順序。
查詢優化器在執行查詢時通常會選擇最有效的方法。但如果沒有索引,則查詢優化器必須掃描表。您的任務是設計並創建最適合您的環境的索引,以便查詢優化器可以從多個有效的索引中選擇。SQL Server 提供的資料庫引擎優化顧問可以幫助分析資料庫環境並選擇適當的索引。
三、索引怎麼用
索引其實關鍵目的是為了加快檢索速度而建立的,所以,怎麼用索引是資料庫系統本身的事情,作為資料庫設計或使用者,設計並創建好索引然後體驗加上索引後的查詢變快的感覺就行了。所以,索引怎麼用就變為了「怎麼創建合適的索引」,以下說明這個問題:
索引設計不佳和缺少索引是提高資料庫和應用程序性能的主要障礙。設計高效的索引對於獲得良好的資料庫和應用程序性能極為重要。為資料庫及其工作負荷選擇正確的索引是一項需要在查詢速度與更新所需開銷之間取得平衡的復雜任務。如果索引較窄,或者說索引關鍵字中只有很少的幾列,則需要的磁碟空間和維護開銷都較少。而另一方面,寬索引可覆蓋更多的查詢。您可能需要試驗若干不同的設計,才能找到最有效的索引。可以添加、修改和刪除索引而不影響資料庫架構或應用程序設計。因此,應試驗多個不同的索引而無需猶豫。
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 時,將不持有長期表鎖以繼續對基礎表的查詢或更新。
❺ oracle資料庫索引種類,分別什麼情況下使用
1.
b-tree索引
Oracle資料庫中最常見的索引類型是b-tree索引,也就是B-樹索引,以其同名的計算科學結構命名。CREATE
INDEX語句時,默認就是在創建b-tree索引。沒有特別規定可用於任何情況。
2.
點陣圖索引(bitmap
index)
點陣圖索引特定於該列只有幾個枚舉值的情況,比如性別欄位,標示欄位比如只有0和1的情況。
3.
基於函數的索引
比如經常對某個欄位做查詢的時候是帶函數操作的,那麼此時建一個函數索引就有價值了。
4.
分區索引和全局索引
這2個是用於分區表的時候。前者是分區內索引,後者是全表索引
5.
反向索引(REVERSE)
這個索引不常見,但是特定情況特別有效,比如一個varchar(5)位欄位(員工編號)含值
(10001,10002,10033,10005,10016..)
這種情況默認索引分布過於密集,不能利用好伺服器的並行
但是反向之後10001,20001,33001,50001,61001就有了一個很好的分布,能高效的利用好並行運算。
6.HASH索引
HASH索引可能是訪問資料庫中數據的最快方法,但它也有自身的缺點。集群鍵上不同值的數目必須在創建HASH集群之前就要知道。需要在創建HASH集群的時候指定這個值。使用HASH索引必須要使用HASH集群。
❻ 資料庫中的索引有什麼用
先正面回答你的問題
數據是否重復不是建立索引的重要依據,甚至都不是依據。
只要不完全重復(所有元組的該元素都一樣),那麼建立索引就是有意義的。
即使當前數據完全重復,也不是不能建立索引,這種情況有點復雜,不細說了。
對於你後面的疑問,可以給你一個如何建立索引的忠告,「如何查就如何建」。
索引的建立,唯一的原因就是為了查詢(廣義的查詢),實際上建立索引會使得數據存儲所佔空間變大,有時索引所佔的空間會查過數據本身的空間。索引的建立也會使得數據插入時變慢,特殊情況下,慢的難以忍受,所以dba的重要工作之一,就是檢查索引層級並優化。
索引建立的唯一好處,就是按照索引查詢時,變快了。type,status這2個欄位是否適合建立索引,就要看你是否要按照這2個欄位進行檢索。而檢索的順序決定了如何建立索引。
對於索引類型和索引方式,我建議就
normal
和
btree
就適用於大多數情況。若你參與的是一個大數據處理項目,對數據存儲和檢索有特別要求,那麼需要分析多個層面,比如數據吞吐量、數據的方差、平均差等等很多參數才考慮是否用聚集索引等(mysql好像還沒聚集索引),至於是否是唯一索引,我建議不使用,即使能判定數據是唯一的也不要用,全文索引也沒有必要。
❼ 資料庫索引是什麼,有什麼優點和缺點
資料庫中索引的優缺點
為什麼要創建索引呢?這是因為,創建索引可以大大提高系統的性能。第一,通過創建唯一性索引,可以保證資料庫表中每一行數據的唯一性。第二,可以大大加快數據的檢索速度,這也是創建索引的最主要的原因。第三,可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。第四,在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。第五,通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。
也許會有人要問:增加索引有如此多的優點,為什麼不對表中的每一個列創建一個索引呢?這種想法固然有其合理性,然而也有其片面性。雖然,索引有許多優點,但是,為表中的每一個列都增加索引,是非常不明智的。這是因為,增加索引也有許多不利的一個方面。第一,創建索引和維護索引要耗費時間,這種時間隨著數據量的增加而增加。第二,索引需要佔物理空間,除了數據表占數據空間之外,每一個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大。第三,當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。
索引是建立在資料庫表中的某些列的上面。因此,在創建索引的時候,應該仔細考慮在哪些列上可以創建索引,在哪些列上不能創建索引。一般來說,應該在這些列上創建索引,例如:在經常需要搜索的列上,可以加快搜索的速度;在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;在經常需要根據范圍進行搜索的列上創建索引,因為索引已經排序,其指定的范圍是連續的;在經常需要排序的列上創建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;在經常使用在WHERE子句中的列上面創建索引,加快條件的判斷速度。
同樣,對於有些列不應該創建索引。一般來說,不應該創建索引的的這些列具有下列特點:第一,對於那些在查詢中很少使用或者參考的列不應該創建索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。第二,對於那些只有很少數據值的列也不應該增加索引。這是因為,由於這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行佔了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,並不能明顯加快檢索速度。第三,對於那些定義為text,
image和bit數據類型的列不應該增加索引。這是因為,這些列的數據量要麼相當大,要麼取值很少。第四,當修改性能遠遠大於檢索性能時,不應該創建索引。這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大於檢索性能時,不應該創建索引。
❽ 資料庫索引的實現原理
資料庫索引的實現原理
一、概述資料庫索引,是資料庫管理系統中一個排序的數據結構,以協助快速查詢、更新資料庫表中數據。索引的實現通常使用B樹及其變種B+樹。在數據之外,資料庫系統還維護著滿足特定查找演算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找演算法。這種數據結構,就是索引。其實說穿了,索引問題就是一個查找問題。二、索引的原理當我們的業務產生了大量的數據時,查找數據的效率問題也就隨之而來,所以我們可以通過為表設置索引,而為表設置索引要付出代價的:一是增加了資料庫的存儲空間,二是在插入和修改數據時要花費較多的時間(因為索引也要隨之變動)。
上圖展示了一種可能的索引方式。左邊是數據表,一共有兩列七條記錄,最左邊的是數據記錄的物理地址(注意邏輯上相鄰的記錄在磁碟上也並不是一定物理相鄰的)。為了加快Col2的查找,可以維護一個右邊所示的二叉查找樹,每個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就可以運用二叉查找在O(log2n)的復雜度內獲取到相應數據。索引是建立在資料庫表中的某些列的上面。在創建索引的時候,應該考慮在哪些列上可以創建索引,在哪些列上不能創建索引。一般來說,應該在這些列上創建索引:在經常需要搜索的列上,可以加快搜索的速度;在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;在經常需要根據范圍進行搜索的列上創建索引,因為索引已經排序,其指定的范圍是連續的;在經常需要排序的列上創建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;在經常使用在WHERE子句中的列上面創建索引,加快條件的判斷速度。創建索引可以大大提高系統的性能第一,通過創建唯一性索引,可以保證資料庫表中每一行數據的唯一性。第二,可以大大加快數據的檢索速度,這也是創建索引的最主要的原因。第三,可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。第四,在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。第五,通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。也許會有人要問:增加索引有如此多的優點,為什麼不對表中的每一個列創建一個索引呢?因為,增加索引也有許多不利的方面。創建索引的弊端第一,創建索引和維護索引要耗費時間,這種時間隨著數據量的增加而增加。第二,索引需要佔物理空間,除了數據表占數據空間之外,每一個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大。第三,當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。同樣,對於有些列不應該創建索引。一般來說,不應該創建索引的的這些列具有下列特點:第一,對於那些在查詢中很少使用或者參考的列不應該創建索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。第二,對於那些只有很少數據值的列也不應該增加索引。這是因為,由於這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行佔了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,並不能明顯加快檢索速度。第三,對於那些定義為text, image和bit數據類型的列不應該增加索引。這是因為,這些列的數據量要麼相當大,要麼取值很少。第四,當修改性能遠遠大於檢索性能時,不應該創建索引。這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大於檢索性能時,不應該創建索引。三、索引的類型根據資料庫的功能,可以在資料庫設計器中創建三種索引:唯一索引、主鍵索引和聚集索引。唯一索引唯一索引是不允許其中任何兩行具有相同索引值的索引。當現有數據中存在重復的鍵值時,大多數資料庫不允許將新創建的唯一索引與表一起保存。資料庫還可能防止添加將在表中創建重復鍵值的新數據。例如,如果在employee表中職員的姓(lname)上創建了唯一索引,則任何兩個員工都不能同姓。主鍵索引資料庫表經常有一列或列組合,其值唯一標識表中的每一行。該列稱為表的主鍵。在資料庫關系圖中為表定義主鍵將自動創建主鍵索引,主鍵索引是唯一索引的特定類型。該索引要求主鍵中的每個值都唯一。當在查詢中使用主鍵索引時,它還允許對數據的快速訪問。聚集索引在聚集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能包含一個聚集索引。如果某索引不是聚集索引,則表中行的物理順序與鍵值的邏輯順序不匹配。與非聚集索引相比,聚集索引通常提供更快的數據訪問速度。四、局部性原理與磁碟預讀由於存儲介質的特性,磁碟本身存取就比主存慢很多,再加上機械運動耗費,磁碟的存取速度往往是主存的幾百分分之一,因此為了提高效率,要盡量減少磁碟I/O。為了達到這個目的,磁碟往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個位元組,磁碟也會從這個位置開始,順序向後讀取一定長度的數據放入內存。這樣做的理論依據是計算機科學中著名的局部性原理:當一個數據被用到時,其附近的數據也通常會馬上被使用。程序運行期間所需要的數據通常比較集中。由於磁碟順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對於具有局部性的程序來說,預讀可以提高I/O效率。預讀的長度一般為頁(page)的整倍數。頁是計算機管理存儲器的邏輯塊,硬體及操作系統往往將主存和磁碟存儲區分割為連續的大小相等的塊,每個存儲塊稱為一頁(在許多操作系統中,頁得大小通常為4k),主存和磁碟以頁為單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁碟發出讀盤信號,磁碟會找到數據的起始位置並向後連續讀取一頁或幾頁載入內存中,然後異常返回,程序繼續運行。五、B樹和B+樹數據結構1、B樹B樹中每個節點包含了鍵值和鍵值對於的數據對象存放地址指針,所以成功搜索一個對象可以不用到達樹的葉節點。成功搜索包括節點內搜索和沿某一路徑的搜索,成功搜索時間取決於關鍵碼所在的層次以及節點內關鍵碼的數量。在B樹中查找給定關鍵字的方法是:首先把根結點取來,在根結點所包含的關鍵字K1,…,kj查找給定的關鍵字(可用順序查找或二分查找法),若找到等於給定值的關鍵字,則查找成功;否則,一定可以確定要查的關鍵字在某個Ki或Ki+1之間,於是取Pi所指的下一層索引節點塊繼續查找,直到找到,或指針Pi為空時查找失敗。2、B+樹B+樹非葉節點中存放的關鍵碼並不指示數據對象的地址指針,非也節點只是索引部分。所有的葉節點在同一層上,包含了全部關鍵碼和相應數據對象的存放地址指針,且葉節點按關鍵碼從小到大順序鏈接。如果實際數據對象按加入的順序存儲而不是按關鍵碼次數存儲的話,葉節點的索引必須是稠密索引,若實際數據存儲按關鍵碼次序存放的話,葉節點索引時稀疏索引。B+樹有2個頭指針,一個是樹的根節點,一個是最小關鍵碼的葉節點。所以 B+樹有兩種搜索方法:一種是按葉節點自己拉起的鏈表順序搜索。一種是從根節點開始搜索,和B樹類似,不過如果非葉節點的關鍵碼等於給定值,搜索並不停止,而是繼續沿右指針,一直查到葉節點上的關鍵碼。所以無論搜索是否成功,都將走完樹的所有層。B+ 樹中,數據對象的插入和刪除僅在葉節點上進行。這兩種處理索引的數據結構的不同之處:1、B樹中同一鍵值不會出現多次,並且它有可能出現在葉結點,也有可能出現在非葉結點中。而B+樹的鍵一定會出現在葉結點中,並且有可能在非葉結點中也有可能重復出現,以維持B+樹的平衡。2、因為B樹鍵位置不定,且在整個樹結構中只出現一次,雖然可以節省存儲空間,但使得在插入、刪除操作復雜度明顯增加。B+樹相比來說是一種較好的折中。3、B樹的查詢效率與鍵在樹中的位置有關,最大時間復雜度與B+樹相同(在葉結點的時候),最小時間復雜度為1(在根結點的時候)。而B+樹的時候復雜度對某建成的樹是固定的。六、B/+Tree索引的性能分析到這里終於可以分析B-/+Tree索引的性能了。上文說過一般使用磁碟I/O次數評價索引結構的優劣。先從B-Tree分析,根據B-Tree的定義,可知檢索一次最多需要訪問h個節點。資料庫系統的設計者巧妙利用了磁碟預讀原理,將一個節點的大小設為等於一個頁,這樣每個節點只需要一次I/O就可以完全載入。為了達到這個目的,在實際實現B-Tree還需要使用如下技巧:每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁里,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。B-Tree中一次檢索最多需要h-1次I/O(根節點常駐內存),漸進復雜度為O(h)=O(logdN)。一般實際應用中,出度d是非常大的數字,通常超過100,因此h非常小(通常不超過3)。而紅黑樹這種結構,h明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性,所以紅黑樹的I/O漸進復雜度也為O(h),效率明顯比B-Tree差很多。綜上所述,用B-Tree作為索引結構效率是非常高的。