如何為mysql建立索引

2021-08-26 12:08:37 字數 3295 閱讀 3237

前些時候,一位頗高階的程式設計師居然問我什麼叫做索引,令我感到十分的驚奇,我想這絕不會是滄海一粟,因為有成千上萬的開發者(可能大部分是使用mysql的)都沒有受過有關資料庫的正規培訓,儘管他們都為客戶做過一些開發,但卻對如何為資料庫建立適當的索引所知較少,因此我起了寫一篇相關文章的念頭。

最普通的情況,是為出現在where子句的字段建乙個索引。為方便講述,我們先建立乙個如下的表。

code**如下:

create table mytable (

id serial primary key,

category_id int not null default 0,

user_id int not null default 0,

adddate int not null default 0

);很簡單吧,不過對於要說明這個問題,已經足夠了。如果你在查詢時常用類似以下的語句:

select * from mytable where category_id=1; 

最直接的應對之道,是為category_id建立乙個簡單的索引:

create index mytable_categoryid 

on mytable (category_id);

注意到我在命名時的習慣了嗎?我使用"表名_欄位1名_欄位2名"的方式。你很快就會知道我為什麼這樣做了。

現在你已經為適當的字段建立了索引,不過,還是有點不放心吧,你可能會問,資料庫會真正用到這些索引嗎?測試一下就ok,對於大多數的資料庫來說,這是很容易的,只要使用explain命令:

explain

select * from mytable 

where category_id=1 and user_id=2;

this is what postgres 7.1 returns (exactly as i expected) 

notice: query plan:

index scan using mytable_categoryid_userid on 

mytable (cost=0.00..2.02 rows=1 width=16)

explain

以上是postgres的資料,可以看到該資料庫在查詢的時候使用了乙個索引(乙個好開始),而且它使用的是我建立的第二個索引。看到我上面命名的好處了吧,你馬上知道它使用適當的索引了。

接著,來個稍微複雜一點的,如果有個order by字句呢?不管你信不信,大多數的資料庫在使用order by的時候,都將會從索引中受益。

select * from mytable 

where category_id=1 and user_id=2

order by adddate desc;

有點迷惑了吧?很簡單,就象為where字句中的字段建立乙個索引一樣,也為order by的字句中的字段建立乙個索引:

create index mytable_categoryid_userid_adddate

on mytable (category_id,user_id,adddate);

注意: "mytable_categoryid_userid_adddate" 將會被截短為

"mytable_categoryid_userid_addda"

create

explain select * from mytable

where category_id=1 and user_id=2

order by adddate desc;

notice: query plan:

sort (cost=2.03..2.03 rows=1 width=16)

-> index scan using mytable_categoryid_userid_addda 

on mytable (cost=0.00..2.02 rows=1 width=16)

explain

看看explain的輸出,好象有點恐怖啊,資料庫多做了乙個我們沒有要求的排序,這下知道效能如何受損了吧,看來我們對於資料庫的自身運作是有點過於樂觀了,那麼,給資料庫多一點提示吧。

為了跳過排序這一步,我們並不需要其它另外的索引,只要將查詢語句稍微改一下。這裡用的是postgres,我們將給該資料庫乙個額外的提示--在order by語句中,加入where語句中的字段。這只是乙個技術上的處理,並不是必須的,因為實際上在另外兩個欄位上,並不會有任何的排序操作,不過如果加入,postgres將會知道哪些是它應該做的。

explain select * from mytable 

where category_id=1 and user_id=2

order by category_id desc,user_id desc,adddate desc;

notice: query plan:

index scan backward using 

mytable_categoryid_userid_addda on mytable 

(cost=0.00..2.02 rows=1 width=16)

explain

現在使用我們料想的索引了,而且它還挺聰明,知道可以從索引後面開始讀,從而避免了任何的排序。

以上說得細了一點,不過如果你的資料庫非常巨大,並且每日的頁面請求達上百萬算,我想你會獲益良多的。不過,如果你要做更為複雜的查詢呢,例如將多張表結合起來查詢,特別是where限制字句中的字段是來自不止乙個**時,應該怎樣處理呢?我通常都盡量避免這種做法,因為這樣資料庫要將各個表中的東西都結合起來,然後再排除那些不合適的行,搞不好開銷會很大。

如果不能避免,你應該檢視每張要結合起來的表,並且使用以上的策略來建立索引,然後再用explain命令驗證一下是否使用了你料想中的索引。如果是的話,就ok。不是的話,你可能要建立臨時的表來將他們結合在一起,並且使用適當的索引。

要注意的是,建立太多的索引將會影響更新和插入的速度,因為它需要同樣更新每個索引檔案。對於乙個經常需要更新和插入的**,就沒有必要為乙個很少使用的where字句單獨建立索引了,對於比較小的表,排序的開銷不會很大,也沒有必要建立另外的索引。

以上介紹的只是一些十分基本的東西,其實裡面的學問也不少,單憑explain我們是不能判定該方法是否就是最優化的,每個資料庫都有自己的一些優化器,雖然可能還不太完善,但是它們都會在查詢時對比過哪種方式較快,在某些情況下,建立索引的話也未必會快,例如索引放在乙個不連續的儲存空間時,這會增加讀磁碟的負擔,因此,哪個是最優,應該通過實際的使用環境來檢驗。

在剛開始的時候,如果表不大,沒有必要作索引,我的意見是在需要的時候才作索引,也可用一些命令來優化表,例如mysql可用"optimize table"。

綜上所述,在如何為資料庫建立恰當的索引方面,你應該有一些基本的概念了。

如何為資料庫建立索引

sql 2010 12 15 16 46 54 閱讀41 字型大小 大 中小訂閱 接著,來個稍微複雜一點的,如果有個order by字句呢?不管你信不信,大多數的資料庫在使用order by的時候,都將會從索引中受益。select from mytable where category id 1 a...

mysql怎樣建立索引 mysql如何建立索引?

mysql建立索引的方法 1 使用create table語句配合index或unique關鍵字在建立表的時候直接建立索引 2 使用alter table語句來直接建立索引 3 使用create index語句對錶增加普通索引或unique索引。mysql如何建立索引?1 alter table a...

如何為半結構化資料集建立索引

最近遇到乙個問題 大批量的檔案,每個檔案除了擁有類似於 linux 中struct stat 中的一些基本的元資料外,還存在一系列的 key value 對的擴充套件屬性,現在的需求是,根據使用者提供的 key value 對,快速檢索出匹配的檔案集。對於搜尋來說,暴力搜尋無疑是萬能的,遍歷所有的目...