PostgreSQL
上一頁   下一頁

第七章. 索引和鍵字

內容
鍵字
部分索引
索引主要用來提高資料庫性能。它們應該定義在那些常用於做重複查詢的資格條件的表的列(或者表的字段)上。對索引的不當使用會導致性能的下降,因為更新和插入時間在索引出現時都增加了。

索引還可以用於強制表的主鍵的唯一性。當定義一個索引為 UNIQUE,那麼將不允許多行具有相同的索引字段。這裡的目的是保証數據完整性,而不是改善性能,因此上面的關於不當使用的話並不適用。

可以定義兩種型態的索引:

Postgres 為從索引提供 btree,rtree 和 hash(散列)訪問模式。btree 訪問模式是一個 Lehman-Yao 高並發 btrees 的實現。rtree 訪問模式用 Guttman 的二分算法實現了標準的 rtrees。hash(散列)訪問模式是 Litwin 的線性散列的一個實現。我們單獨的列出這些所用的算法是要表明所有這些訪問模式都是完全動態的並且不必進行周期性的最佳化(例如,像靜態散列算法常見的那樣)。

當一個索引了的字段涉及到使用: <,<=,=,>=,> 之一進行比較時, Postgres 的查詢最佳化器將考慮在掃描中使用 btree 索引。

當一個索引了的字段涉及到使用: <<,&<,&>,>>,@,~=,&& 之一進行比較時,Postgres 的查詢最佳化器將考慮在掃描中使用 rtree 索引。

當一個索引了的字段涉及到使用 = 進行比較時,Postgres 的查詢最佳化器將考慮在掃描中使用散列(hash)索引。

目前,只有 btree 訪問模式支援多字段索引。預設最多可以聲明 16 的關鍵字(這個限制可以在制作 Postgres 時改變)。

可以為某個索引的每個字段聲明一個符號表(operator class)。這個符號表標識該索引用於該字段要使用的符號。例如,一個在4字節整數上的 btree 索引將使用 int4_ops 表﹔這個符號表包括用於4字節整數的比較函數。實際上,該字段型態的預設符號通常就足夠了。擁有符號表的原因是:對於某些數據型態,可能存在多於一個有意義的順序。例如,我們可能想排序兩個復數,既可能通過絕對值,也可能通過實數部分。我們可以通過為該數據型態定義兩個符號表,然後在建立索引時選擇合適的一個來實現這個目的。同樣還有一些有特殊用途的符號表:

下面的查詢顯示所有定義了的符號表:
SELECT am.amname AS acc_name,
       opc.opcname AS ops_name,
       opr.oprname AS ops_comp
    FROM pg_am am, pg_amop amop,
         pg_opclass opc, pg_operator opr
    WHERE amop.amopid = am.oid AND
          amop.amopclaid = opc.oid AND
          amop.amopopr = opr.oid
    ORDER BY acc_name, ops_name, ops_comp
使用 DROP INDEX 刪除一個索引。

關鍵字

作者:Herouth Maoz 寫作。這些最早出現在 1998-03-02 用戶郵件列表裡關於"主鍵(PRIMARY KEY)和唯一約束(UNIQUE constraints)有什麼異同"問題的解答。
Subject: Re: [QUESTIONS] PRIMARY KEY | UNIQUE

        What's the difference between:(下面兩者有何區別?)

              PRIMARY KEY(fields,...) and
              UNIQUE (fields,...)

       - Is this an alias?(這是別名嗎?)
       - If PRIMARY KEY is already unique, then why(如果 PRIMARY KEY 已經唯一,)
         is there another kind of key named UNIQUE?(那麼為什麼有另外一個名為 UNIQUE 型態的鍵字?)
主鍵是用於標識某特定行的字段。例如,身份証(社會安全號)標識一個人。

一個簡單的由字段組成的 UNIQUE 與行標識毫無關系。它只是一個完整性約束。例如,我收集了一些互聯網鏈接。每一個互聯網鏈接用一個唯一的數字標識,也就是主鍵,這個鍵用於表中。

但是,我的應用要求每套集合還要有一個唯一的名稱。因為這樣做的話一個想更改一個互聯網鏈接集合的"人"就可以找出該集合。畢竟,如果你有兩個集合都叫"生命科學",一個被標識成24433,另一個是29882,而24433那個是你要找的,這樣找要比從擁有唯一集合名稱的組中找難得多。

所以,用戶用名稱來選擇集合。因此,對這個資料庫我們確信名稱是唯一的。但是資料庫中沒有其他表與鏈接集合表通過鏈接集合名稱相關。因此這樣做很效率很底。

另外,盡管是唯一的,組名稱實際上並不定義集合!例如,如果某人決定將集合名從"生命科學"改為"生物學",該集合仍然是同一集合,只是名字不同而已。只要名稱仍然是唯一的即可。

所以:

那麼為什麼標準 SQL 語法裡沒有非唯一鍵的顯式定義呢?這是因為索引是與具體實現相關的。SQL 不定義實現,只定義資料庫內數據間的關系, Postgres的確允許非唯一索引,但是用於增強 SQL 鍵字的索引總是唯一的。

因此,你可以通過任何表中的列的組合來查詢該表,不管你是否在這些列上建立了索引。索引只是每個 RDBMS 的實現提供給你的一個工具,以便令常用的查詢可以更有效的進行。有些 RDBMS 可能會給你另外一些工具,例如在主存裡保留一個鍵值。它們有一些特殊的命令,例如

CREATE MEMSTORE ON <table> COLUMNS <cols>
(這不是一個實際的命令,只是一個例子)。

實際上,當你創建一個主鍵或一個域/字段的唯一組合時,在SQL 聲明中沒有任何地方提到創建了索引,用該鍵對數據的檢索也不會比一次順序搜索更高效!

所以,如果你想用一個並不唯一的字段組合作為第二個鍵字,你實際上不用聲明任何東西-只要用那個組合檢索就行了。但是,如果你想令檢索更高效一些,你就不得不依賴你的RDBMS 提供者給你的工具-不管是索引還是我想像的那種 MEMSTORE 命令或是一個智能的 RDBMS,它在你還沒有意識到你常用一套特定的鍵字組合來查詢時就給你創建了索引... (它從經驗中學來)。


上一頁 首頁 下一頁
UNION 查詢 開頭 部分索引