?
本文檔使用 PHP中文網(wǎng)手冊(cè) 發(fā)布
假設(shè)有像下面這樣一個(gè)表:
CREATE TABLE test1 ( id integer, content varchar );
并且進(jìn)行大量的類似下面這樣的語(yǔ)句進(jìn)行查詢:
SELECT content FROM test1 WHERE id = constant;
通常,數(shù)據(jù)庫(kù)系統(tǒng)不得不一行一行地掃描整個(gè)test1表以尋找所有匹配的記錄。 如果在test1里面有許多行,但是只返回少數(shù)幾行(可能是零行或一行), 那么上面這個(gè)方法可就很差勁了。如果我們讓數(shù)據(jù)庫(kù)系統(tǒng)在 id列上維護(hù)一個(gè)索引用于定位匹配的行。 這樣,數(shù)據(jù)庫(kù)系統(tǒng)只需要在搜索樹(shù)中走少數(shù)的幾層就可以找到匹配行。
在大多數(shù)非小說(shuō)的書籍里面都使用了類似這樣的方法: 在書的背后收集著讀者會(huì)經(jīng)常查找的術(shù)語(yǔ)和概念的索引,并按照字母順序排列。 有興趣的讀者可以快速地掃描該索引并且切換到合適的頁(yè),因此不用閱讀整本書就能查找到感興趣的位置。 作者的任務(wù)之一就是預(yù)計(jì)哪些項(xiàng)是讀者最需要查找的東西,與之類似,預(yù)計(jì)哪些索引可以帶來(lái)便利也是數(shù)據(jù)庫(kù)程序員的任務(wù)。
下面的命令可以用于在id列上創(chuàng)建前面討論過(guò)的索引:
CREATE INDEX test1_id_index ON test1 (id);
索引名字test1_id_index可以自由選擇,但是應(yīng)該選那些稍后可以讓你回憶起索引含義的名字。
要?jiǎng)h除一個(gè)索引,使用DROP INDEX命令??梢栽谌魏螘r(shí)候向表里增加索引或者從表中刪除索引。
一旦你創(chuàng)建了索引,那么就不需要更多干涉了:當(dāng)該表被修改后,系統(tǒng)會(huì)自動(dòng)更新索引,并且當(dāng)對(duì)表進(jìn)行查詢時(shí),如果系統(tǒng)認(rèn)為使用索引比進(jìn)行順序的表掃描更有效時(shí),系統(tǒng)會(huì)選擇使用索引進(jìn)行查詢。 不過(guò)你可能必須經(jīng)常性地運(yùn)行ANALYZE命令以更新統(tǒng)計(jì)信息,好讓查詢規(guī)劃器能夠做出有訓(xùn)練有素的判斷。 參見(jiàn)Chapter 14獲取關(guān)于如何獲知是否使用了索引的信息,以及在什么時(shí)候、什么原因下規(guī)劃器會(huì)決定不使用索引。
索引對(duì)帶搜索條件的UPDATE和DELETE命令也有好處。 索引更可以用于表鏈接查詢。因此,如果你定義了索引的列是鏈接條件的一部分,那么它可以顯著提高鏈接的查詢速度。
在一個(gè)巨大的表上創(chuàng)建索引可能會(huì)消耗大量的時(shí)間。缺省時(shí),PostgreSQL允許在創(chuàng)建索引的同時(shí)讀取表(SELECT), 但是寫入表(INSERT, UPDATE, DELETE)的動(dòng)作將被阻塞到索引創(chuàng)建完畢。在生產(chǎn)環(huán)境下這種阻塞通常是不可接受的, 因此也允許在創(chuàng)建索引的同時(shí)寫入表,但是有一些警告需要注意,更多信息參見(jiàn)Building Indexes Concurrently。
創(chuàng)建索引之后,它必須和表保持同步。這些操作增加了數(shù)據(jù)操作的負(fù)荷。因此我們應(yīng)該把那些非關(guān)鍵或者根本用不上的索引刪除掉。