通過前面的幾篇文章,我們初步了解了索引的一些特徵,這將有助於設計出最佳的索引。
一、從資料庫的角度進行設計
1. 索引的寬度
索引寬度,即索引的鍵占用了多少個位元組。影響索引寬度有2個因素:一是引用的列,二是索的資料型別。原則上,索引應保持較窄,就是說,列要盡可能少,列的資料型別要盡可能精簡。
不能將 ntext、text、image、varchar(max)、nvarchar(max) 和 varbinary(max) 資料型別的列指定為索引鍵列。不過,varchar(max)、nvarchar(max)、varbinary(max) 和 xml 資料型別的列可以作為非鍵索引列參與非聚集索引。
設計時注意以下幾類資料型別:
(1)日期型 vs. 日期時間型
舊版本的sql server只有日期時間型datetime(1753-01-01 00:00:00.000到 9999-12-31 23:59:59.999,8個位元組)和smalldatetime(範圍從1900-01-01 00:00到 2079-06-06 23:59,4個位元組)。sql server 2008 新增了多種日期型別,其中包括date(範圍從0001-01-01 到 9999-12-31,3個位元組)和time。如果某個列經常只需要查詢日期,建議將實際業務的datetime拆分為date和time型別的2個列,並在date型別的列上建立索引。
(2)整型 vs. 字元型
有些編號,例如客戶id,如果業務上沒有特別要求,那麼使用整型是最佳選擇。因為,整型的範圍從 -2,147,483,648 到 2,147,483,647 ,佔4個位元組,而同樣範圍的字元型卻需要10個位元組。此外,對於小範圍的編號,smallint也是不錯的選擇,它的範圍從 -32,768 到 32,767 ,只佔2個位元組。
(3)uniqueidentifier列(guid)vs. identity列
有些程式設計師希望每行有乙個唯一標識,於是將guid作為標識。如果在 sql server 的表定義中將列型別指定為 uniqueidentifier,則列的值就為 guid 型別,佔16個位元組。
create table table1( myid uniqueidentifier, myname varchar(10) )
insert into table1 values (newid(),'noname')
select * from table1
從程式設計的角度來看,上述設計並無不妥。但如果在這個列上建立索引(尤其是聚集索引),對效能可能有很大的影響。建議改用identity列。
首先,guid占用16個位元組;而identity列為int型別,僅占用4個位元組。對比之下,後者的索引寬度可以縮減12個位元組。
其次,guid是隨機的,導致索引的分頁現象非常嚴重;而identity列的值一般是連續增長,因此不會造成索引分頁。
create table table2 ( myid int identity, myname varchar(10) )
insert into table2 (myname) values ('noname')
select * from table2
dbcc checkident('table2', noreseed)
或者,使用identity函式。
select identity(int, 1,1) as id_num
into newtable
from oldtable
2. 索引維護的開銷
(1)權衡讀與寫的數量
使用多個索引可以提高資料的查詢(例如 select 語句)的效能,因為查詢優化器有更多的索引可供選擇,從而可以確定最快的訪問方法。
但是,乙個表如果建有大量索引會影響 insert、update、delete 和 merge 語句的效能,因為當表中的資料更改時,所有索引都須進行適當的維護。
避免對經常更新的表進行過多的索引。
(2)索引盡可能窄
避免新增不必要的列。新增太多索引列可能對磁碟空間和索引維護效能產生負面影響。
3. 唯一索引
檢查列的唯一性。在同乙個列組合的唯一索引而不是非唯一索引提供了有關使索引更有用的查詢優化器的附加資訊。
4. 聚集索引優化
請保持較短的索引鍵長度。另外,對唯一列或非空列建立聚集索引可以使聚集索引獲益。
二、從查詢的角度
設計索引時,應考慮以下查詢準則:
(1)小表的索引
對小表進行索引可能不會產生優化效果,因為查詢優化器在遍歷用於搜尋資料的索引時,花費的時間可能比執行簡單的表掃瞄還長。因此,小表的索引可能從來不用,卻仍必須在表中的資料更改時進行維護。
(2)索引覆蓋
為經常用於查詢中的謂詞和聯接條件的所有列建立非聚集索引。
涵蓋索引可以提高查詢效能,因為符合查詢要求的全部資料都存在於索引本身中。也就是說,只需要索引頁,而不需要表的資料頁或聚集索引來檢索所需資料,因此,減少了總體磁碟 i/o。例如,對某一表(其中對列 a、列 b 和列 c 建立了組合索引)的列 a 和列 b 的查詢,僅僅從該索引本身就可以檢索指定資料。
(3)降低索引維護的開銷
將插入或修改盡可能多的行的查詢寫入單個語句內,而不要使用多個查詢更新相同的行。僅使用乙個語句,就可以利用優化的索引維護。
(4)索引的效率
評估查詢型別以及如何在查詢中使用列。例如,在完全匹配查詢型別中使用的列就適合用於非聚集索引或聚集索引。
在列中檢查資料分布。通常情況下,為包含很少唯一值的列建立索引或在這樣的列上執行聯接將導致長時間執行的查詢。這是資料和查詢的基本問題,通常不識別這種情況就無法解決這類問題。例如,如果物理**簿按姓的字母順序排序,而城市裡所有人的姓都是 smith 或 jones,則無法快速找到某個人。
(5)索引中列的順序
如果索引包含多個列,則應考慮列的順序。用於等於 (=)、大於 (>)、小於 (<) 或 between 搜尋條件的 where 子句或者參與聯接的列應該放在最前面。其他列應該基於其非重複級別進行排序,就是說,從最不重複的列到最重複的列。
例如,如果將索引定義為 lastname、firstname,則該索引在搜尋條件為 where lastname = 'smith' 或 where lastname = smith and firstname like 'j%' 時將很有用。不過,查詢優化器不會將此索引用於基於 firstname (where firstname = 'jane') 而搜尋的查詢。
索引 聚集索引設計指南
每個表只能有乙個聚集索引,因為資料行本身只能按乙個順序儲存.有關聚集索引體系結構的詳細資訊,請參閱 聚集索引結構.每個表幾乎都對列定義聚集索引來實現下列功能 uniqueifieruniqueifier 查詢注意事項 在建立聚集索引之前,應先了解資料是如何被訪問的.考慮對具有以下特點的查詢使用聚集索...
mysql優化(5) 索引優化
建立合理地索引能夠提公升資料庫的查詢效率,但是如果建立的索引不合理,不僅會降低資料庫的插入 修改 刪除的效率,而且會降低資料庫的查詢效率。其中最主要的是組合索引的建立和優化。mysql允許在相同的列上建立多個索引,無論索引是否有實際的意義。且索引一旦被建立,就需要mysql單獨維護重複的索引,且my...
三 索引優化(6)篩選索引
一 概念 篩選索引是一種經過優化的非聚集索引,尤其適用於涵蓋從定義完善的資料子集中選擇資料的查詢。篩選索引使用篩選謂詞對錶中的部分行進行索引。二 優勢 篩選索引與全表索引相比具有以下優點 1 提高了查詢效能和計畫質量 設計良好的篩選索引可以提高查詢效能和執行計畫質量,因為它比全表非聚集索引小並且具有...