<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 35.14\. 擴展索引接口 到目前為止描述的過程可以讓你定義一個新類型、新函數、新操作符。但是, 還不能在一個新數據類型的字段上面定義一個索引。為了達到這個目的, 必須為新數據類型定義一個_操作符類_。下面將使用一個真實的例子來描述操作符類: 一個用于 B-tree 訪問方法的新操作符類,它保存復數并按照絕對值遞增的順序排序。 操作符類可以分類到_操作符族_,用以顯示語義兼容的類之間的關系。 當只包含一個數據類型時,一個操作符類就足夠了,所以我們首先關注這種情況, 然后再轉到操作符族。 ## 35.14.1\. 索引方法和操作符類 `pg_am`表為每個索引方法(內部稱作訪問方法)都包含一條記錄。 對表的普通訪問方法支持內建于PostgreSQL , 但所有索引方法在`pg_am`里都有描述。 可以通過定義要求的接口過程并在`pg_am` 里創建一個新行的辦法增加一個索引訪問方法,不過這些些遠遠超出了本章的內容 (參閱[Chapter 54](#calibre_link-84))。 一個索引方法的過程并不直接知道任何該索引方法將要操作的數據類型的信息。 而是_操作符類_ 表明索引方法在操作特定數據類型的時候需要使用的操作集合。 操作符類的名稱的由來是因為它們聲明是一種索引可以使用的`WHERE` 子句的操作符集(也就是可以轉化成一個索引掃描條件)。 一個操作符類也可以聲明一些索引方法需要的內部操作的_支持過程_, 但是它們并不直接和可以與索引一起使用的`WHERE`子句操作符相關。 可以為同一個數據類型和索引方法定義多個操作符類。這么做的結果是, 可以為一種數據類型定義多套索引語義。比如, 一個 B-tree 索引要求為它操作的每種數據類型定義一個排序順序。 對于一個復數數據類型而言,有一個通過復數絕對值對數據排序的 B-tree 操作符類可能會有用, 還有一個是用實部排序,等等。通常其中一個操作符類會被認為最常用的, 并且被標記為該數據類型和索引方法的缺省操作符類。 同樣的操作符類名字可以用于多種不同的索引方法(比如 B-tree 和 Hash 訪問方法都有叫 `int4_ops`的操作符類),但是每個這樣的表都是一個獨立的實體,必須分別定義。。 ## 35.14.2\. 索引方法策略 和一種操作符類相關聯的操作符是通過"策略號"標識的, 策略號用于標識每種操作符在它的操作符類環境里的語義。比如,B-tree 對鍵字有嚴格的排序要求, 小于到大于,因此,像"小于"和"大于或等于"這樣的操作符都是 B-tree 所感興趣的。 因為PostgreSQL允許用戶定義操作符,PostgreSQL 無法僅通過查看操作符的名字(比如`&lt;`或`&gt;=`)就明白它進行的比較是什么。 實際上,索引方法定義了一套"策略",它可以看作一般性的操作符。 每種操作符類顯示對于特定數據類型而言,是哪種實際操作符對應每種策略以及解釋索引的語義。 B-tree 索引定義了五種策略。在[Table 35-2](#calibre_link-995)中顯示。 **Table 35-2\. B-tree 策略** | 操作 | 策略號 | | --- | --- | | 小于 | 1 | | 小于或等于 | 2 | | 等于 | 3 | | 大于或等于 | 4 | | 大于 | 5 | Hash 索引只支持平等的比較,因此它們只定義了一個策略, 在[Table 35-3](#calibre_link-996)里顯示。 **Table 35-3\. Hash 策略** | 操作 | 策略號 | | --- | --- | | 等于 | 1 | GiST 索引甚至更加靈活:它們根本就沒有固定的策略集。實際上, 是每個特定 GiST 操作符類的"一致性"支持過程解釋策略號是什么樣子。作為示例, 有幾個內置的 GiST 索引操作符類索引二維幾何對象,提供[Table 35-4](#calibre_link-997) 中所示的"R-tree"策略。其中的四個是兩維測試(重疊、相同、包含、包含于); 四個只考慮 x 坐標、四個對 y 坐標進行同樣測試。 **Table 35-4\. GiST 兩維"R-tree"策略** | 操作 | 策略號 | | --- | --- | | 嚴格地在...左邊 | 1 | | 不擴展到...右邊 | 2 | | 重疊 | 3 | | 不延伸到...左邊 | 4 | | 嚴格地在...右邊 | 5 | | 相同 | 6 | | 包含 | 7 | | 包含于 | 8 | | 不擴展到...上面 | 9 | | 嚴格地在...下面 | 10 | | 嚴格地在...上面 | 11 | | 不擴展到...下面 | 12 | SP-GiST索引在靈活性方面與 GiST 索引類似:它們都沒有一個固定的策略集, 而是由每個操作符類的支持過程根據操作符類的定義來解釋策略號。作為示例, [Table 35-5](#calibre_link-998)顯示了內置的點操作符類使用的策略號。 **Table 35-5\. SP-GiST 點策略** | 操作 | 策略號 | | --- | --- | | 嚴格在左邊 | 1 | | 嚴格在右邊 | 5 | | 相同 | 6 | | 包含 | 8 | | 嚴格在下面 | 10 | | 嚴格在上面 | 11 | GIN 索引與 GiST 索引和SP-GiST 索引類似:它們都沒有一個固定的策略集, 而是由每個操作符類的支持過程根據操作符類的定義來解釋策略號。作為示例, [Table 35-6](#calibre_link-999)顯示了內置的數組操作符類使用的策略號。 **Table 35-6\. GIN 數組策略** | 操作 | 策略號 | | --- | --- | | 重疊 | 1 | | 包含 | 2 | | 包含于 | 3 | | 相等 | 4 | 請注意,所有上述操作符都返回布爾值。實際上,所有定義為索引方法搜索操作符的操作符都必須返回 `boolean`類型,因為它們必須出現在一個`WHERE`子句的頂層, 這樣才能被一個索引使用。(某些索引訪問方法也支持_順序操作符_, 它們通常不反悔Boolean值;這個特征在[Section 35.14.7](#calibre_link-945)里討論。) ## 35.14.3\. 索引方法支持過程 有時候,策略的信息還不足以讓系統決定如何使用某個索引。在實際中, 索引方法需要附加的一些過程來保證正常工作。例如, B-tree 索引方法必須能夠比較兩個鍵字以決定其中一個是大于、等于、還是小于另外一個。 類似的還有 Hash 索引方法必須能夠在鍵值上計算散列值。 這些操作和 SQL 命令條件里使用的操作符并不對應;它們是在內部被索引方法使用的管理過程。 就像策略一樣,操作符類聲明在一定的數據類型和語義解釋的條件下, 哪個特定函數對應這些角色中的哪一個。索引方法聲明它需要的函數集, 而操作符類通過給它們賦予通過索引方法指定的"支持函數編號"來標識要正確使用的函數。 B-tree 需要一個支持函數,并且允許在操作符類作者的選項中提供第二個, 就像[Table 35-7](#calibre_link-1000)里顯示的那樣。 **Table 35-7\. B-tree 支持函數** | 函數 | 支持號 | | --- | --- | | 比較兩個鍵字并且返回一個小于、等于、大于零的整數,標識第一個鍵字小于、 等于、大于第二個鍵字。 | 1 | | 返回C-callable排序支持函數的地址,記錄在`utils/sortsupport.h`(可選) | 2 | Hash 索引也需要一個支持函數,在[Table 35-8](#calibre_link-1001)里顯示。 **Table 35-8\. Hash 支持函數** | 函數 | 支持號 | | --- | --- | | 為一個鍵字計算散列值 | 1 | GiST 索引需要七種支持函數,和一個可選的函數,在[Table 35-9](#calibre_link-1002)里顯示。 (更多信息請參考[Chapter 55](#calibre_link-1003)。) **Table 35-9\. GiST 支持函數** | 函數 | 描述 | 支持號 | | --- | --- | --- | | `consistent` | 檢測鍵是否滿足查詢限定符 | 1 | | `union` | 計算一套鍵的聯合 | 2 | | `compress` | 計算已索引鍵或值的壓縮結果 | 3 | | `decompress` | 計算已壓縮鍵的解壓結果 | 4 | | `penalty` | 計算使用給定的子樹的鍵向子樹中插入新鍵的性能惡化(penalty) | 5 | | `picksplit` | 檢測頁面中的哪個項將被移動到新頁面并為結果頁計算聯合鍵 | 6 | | `equal` | 比較兩個鍵并在相等時返回真 | 7 | | `distance` | 確定鍵到查詢值的距離(可選) | 8 | SP-GiST索引需要五種支持函數,顯示在[Table 35-10](#calibre_link-1004)中。 (更多信息請參閱[Chapter 56](#calibre_link-550)。) **Table 35-10\. SP-GiST 支持函數** | 函數 | 描述 | 支持號 | | --- | --- | --- | | `config` | 提供操作符類的基本信息 | 1 | | `choose` | 確定如何將一個新值插入一個內在的元組 | 2 | | `picksplit` | 確定如何分區一組值 | 3 | | `inner_consistent` | 確定哪個子分區需要為一個查詢搜索 | 4 | | `leaf_consistent` | 確定哪個鍵滿足查詢條件 | 5 | GIN 索引需要四種支持函數,和一個可選的函數,在[Table 35-11](#calibre_link-1005)里顯示。 (更多信息請參閱[Chapter 57](#calibre_link-1006)。) **Table 35-11\. GIN 支持函數** | 函數 | 描述 | 支持號 | | --- | --- | --- | | `compare` | 比較兩個鍵并返回一個小于、等于、大于零的整數,標識第一個鍵小于、等于、大于第二個鍵。 | 1 | | `extractValue` | 從將被索引的值中抽取鍵 | 2 | | `extractQuery` | 從查詢條件中抽取鍵 | 3 | | `consistent` | 檢測值是否匹配查詢條件 | 4 | | `comparePartial` | 比較部分來自查詢的鍵和來自索引的鍵,并返回一個小于、等于、大于零的整數, 標識是否GIN應該忽略這個索引項,將這個項視為一個匹配,或停止索引掃描(可選)。 | 5 | 和搜索操作符不同,支持函數返回特定索引方法預期的數據類型,比如在 B-tree 的情況下, 返回一個有符號整數。每個支持函數的參數的數字和類型也取決于索引方法。 對于B-tree和hash的比較,散列支持函數接受相同的輸入數據類型,同樣操作符也包含在操作符類里, 但是大多數GiST, SP-GiST, 和GIN 支持函數不是這樣的。 ## 35.14.4\. 例子 既然已經了解了這些概念,那么現在就來看一個創建新操作符類的例子。你可以在源代碼的 `src/tutorial/complex.c`和`src/tutorial/complex.sql` 中找到這里講述的例子。操作符類封裝了那些以絕對值順序對復數排序的操作符,這樣就可以選擇 `complex_abs_ops`這個名字。首先,需要一個操作符集合。 用于定義操作符的過程已經在[Section 35.12](#calibre_link-838)討論過了。對這個用于 B-tree 的操作符類, 需要的操作符是: * 絕對值 小于 (策略 1) * 絕對值 小于等于 (策略 2) * 絕對值 等于 (策略 3) * 絕對值 大于等于 (策略 4) * 絕對值 大于 (策略 5) 定義一組相關的比較操作符最不容易出錯的方法是首先寫出 B-tree 比較支持函數, 然后再寫出其它封裝了支持函數的單行函數。這就減少了某些情況下導致不一致結果的機會。 根據這個指引,首先寫出: ``` #define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y) static int complex_abs_cmp_internal(Complex *a, Complex *b) { double amag = Mag(a), bmag = Mag(b); if (amag < bmag) return -1; if (amag > bmag) return 1; return 0; } ``` 現在,小于函數看起來像這樣: ``` PG_FUNCTION_INFO_V1(complex_abs_lt); Datum complex_abs_lt(PG_FUNCTION_ARGS) { Complex *a = (Complex *) PG_GETARG_POINTER(0); Complex *b = (Complex *) PG_GETARG_POINTER(1); PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) < 0); } ``` 其它四個函數的不同之處僅在它們如何將內部函數的結果與零比較。 下一步,基于 SQL 函數聲明函數和操作符: ``` CREATE FUNCTION complex_abs_lt(complex, complex) RETURNS bool AS '_filename_', 'complex_abs_lt' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR < ( leftarg = complex, rightarg = complex, procedure = complex_abs_lt, commutator = > , negator = >= , restrict = scalarltsel, join = scalarltjoinsel ); ``` 指定正確的交換器和"非"操作符以及適當的限制和連接選擇性函數都是非常重要的, 否則優化器將無法有效地利用索引。請注意,小于、等于、 大于三種情況下應該使用不同的選擇性函數。 其它幾個值得注意的問題: * 只可以有一個已命名操作符 `=`把`complex`類型做為其兩個操作數。 這種情況下沒有其它用于`complex`的`=`操作符, 但是如果要制作一個實用的數據類型,可能需要`=`做為復數的普通等于操作。 這種情況下,可能需要使用一些其它操作符名稱來命名`complex_abs_eq`。 * 盡管PostgreSQL可以處理 SQL 名字相同的函數, 只要它們的輸入數據類型不同,而 C 只能處理一個具有給定名稱的全局過程。 因此不能把 C 函數命名為像`abs_eq`這樣簡單的名字。 通常在 C 函數名里面包含數據類型名稱是一個好習慣,這樣就不會和用于其它數據類型的函數沖突。 * 可以制作名為`abs_eq`的 SQL 函數,依靠PostgreSQL 通過輸入數據類型的不同來區分任何其它同名 SQL 函數。為了令例子簡單, 做的函數在 C 層次和 SQL 層次都有相同的名稱。 下一步是注冊 B-tree 需要的"支持過程"。實現這個例子的 C 代碼在包含操作符函數的同一個文件中, 下面是定義函數的方法: ``` CREATE FUNCTION complex_abs_cmp(complex, complex) RETURNS integer AS '_filename_' LANGUAGE C IMMUTABLE STRICT; ``` 既然已經有了需要的操作符和支持過程,就可以最后創建這個操作符類了: ``` CREATE OPERATOR CLASS complex_abs_ops DEFAULT FOR TYPE complex USING btree AS OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 complex_abs_cmp(complex, complex); ``` 這樣就完成了!現在可以在一個`complex`列上創建和使用 B-tree 索引了。 可以把操作符記錄寫得更冗余一些,像: ``` OPERATOR 1 < (complex, complex) , ``` 但是如果該操作符接受的數據類型是定義的操作符類處理的東西,那就沒必要這么做。 上面的例子假設你想把這個新操作符類作為`complex`數據類型的缺省 B-tree 操作符類。 如果你不想這么做,只要去掉關鍵字`DEFAULT`即可。 ## 35.14.5\. 操作符類和操作符族 到目前為止我們都隱含的假定一個操作符類只能處理一種數據類型。 雖然每個索引字段都只能是單獨一種數據類型, 但是使用索引操作符來比較一個已索引字段和一個不同類型的值常常很有用處。 如果有用于與一個操作符類連接的交叉數據類型操作符,通常是其他數據類型有他自己的相關的操作符類。 這對于在相關的類之間明確的建立連接是有幫助的,因為這可以幫助規劃器優化SQL查詢 (尤其對于B-tree操作符類,因為規劃器包含大量的關于如果處理這些問題的信息)。 為了處理這種需求,PostgreSQL使用_操作符族_的概念。一個操作符族包含一個或多個操作符類, 也可以包含可索引的操作符和對應的支持函數,作為一個整體屬于這個族,但不是這個族中的任何一個類。 我們說這樣的操作符和函數是"松散"在族里的,而不是被綁定到一個特定的類。 通常每個操作符類包含一個數據類型操作符,而交叉數據類型操作符是散落在族里的。 所有在一個操作符族里的操作符和函數必須有兼容的語法,兼容性需求是通過索引方法設置的。 你可能想知道為什么費心的挑選出特別的族的子集作為操作符類; 并且甚至為了多種目的類的區分是不相關的,族只對分組感興趣。 定義操作符類的原因是指定多少族需要支持任何特定的索引。如果有一個索引使用一個操作符類, 然后操作符類不能在不刪除索引的情況下被刪除,但是操作符族的其他部分, 即其他操作符類和松散的操作符可以被刪除。因此,一個操作符類應該被指定包含最少的操作符和函數, 應該是在一個特定數據類型上索引工作所需要的適當的操作符和函數, 然后相關的但非重要的操作符可以作為松散的操作符族成員添加。 作為一個例子,PostgreSQL有一個內置的B-tree操作符族`integer_ops`, 它包含操作符類`int8_ops`, `int4_ops`和`int2_ops`, 分別對 `bigint` (`int8`), `integer` (`int4`), 和 `smallint` (`int2`) 字段索引。也包含交叉數據類型比較操作符,允許其中的任意兩種類型進行比較, 所以任意其中一種類型上的索引可以使用其他類型的比較值被搜索到。 族可以通過下面的定義復制: ``` CREATE OPERATOR FAMILY integer_ops USING btree; CREATE OPERATOR CLASS int8_ops DEFAULT FOR TYPE int8 USING btree FAMILY integer_ops AS <!-- -- standard int8 comparisons --> -- 標準 int8 比較 OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint8cmp(int8, int8) , FUNCTION 2 btint8sortsupport(internal) ; CREATE OPERATOR CLASS int4_ops DEFAULT FOR TYPE int4 USING btree FAMILY integer_ops AS <!-- -- standard int4 comparisons --> -- 標準 int4 比較 OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint4cmp(int4, int4) , FUNCTION 2 btint4sortsupport(internal) ; CREATE OPERATOR CLASS int2_ops DEFAULT FOR TYPE int2 USING btree FAMILY integer_ops AS <!-- -- standard int2 comparisons --> --標準 int2 比較 OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint2cmp(int2, int2) , FUNCTION 2 btint2sortsupport(internal) ; ALTER OPERATOR FAMILY integer_ops USING btree ADD <!-- -- cross-type comparisons int8 vs int2 --> -- 交叉類型比較 int8 對 int2 OPERATOR 1 < (int8, int2) , OPERATOR 2 <= (int8, int2) , OPERATOR 3 = (int8, int2) , OPERATOR 4 >= (int8, int2) , OPERATOR 5 > (int8, int2) , FUNCTION 1 btint82cmp(int8, int2) , <!-- -- cross-type comparisons int8 vs int4 --> -- 交叉類型比較 int8 對 int4 OPERATOR 1 < (int8, int4) , OPERATOR 2 <= (int8, int4) , OPERATOR 3 = (int8, int4) , OPERATOR 4 >= (int8, int4) , OPERATOR 5 > (int8, int4) , FUNCTION 1 btint84cmp(int8, int4) , <!-- -- cross-type comparisons int4 vs int2 --> -- 交叉類型比較 int4 對 int2 OPERATOR 1 < (int4, int2) , OPERATOR 2 <= (int4, int2) , OPERATOR 3 = (int4, int2) , OPERATOR 4 >= (int4, int2) , OPERATOR 5 > (int4, int2) , FUNCTION 1 btint42cmp(int4, int2) , <!-- -- cross-type comparisons int4 vs int8 --> -- 交叉類型比較 int4 對 int8 OPERATOR 1 < (int4, int8) , OPERATOR 2 <= (int4, int8) , OPERATOR 3 = (int4, int8) , OPERATOR 4 >= (int4, int8) , OPERATOR 5 > (int4, int8) , FUNCTION 1 btint48cmp(int4, int8) , <!-- -- cross-type comparisons int2 vs int8 --> -- 交叉類型比較 int2 對 int8 OPERATOR 1 < (int2, int8) , OPERATOR 2 <= (int2, int8) , OPERATOR 3 = (int2, int8) , OPERATOR 4 >= (int2, int8) , OPERATOR 5 > (int2, int8) , FUNCTION 1 btint28cmp(int2, int8) , <!-- -- cross-type comparisons int2 vs int4 --> -- 交叉類型比較 int2 對 int4 OPERATOR 1 < (int2, int4) , OPERATOR 2 <= (int2, int4) , OPERATOR 3 = (int2, int4) , OPERATOR 4 >= (int2, int4) , OPERATOR 5 > (int2, int4) , FUNCTION 1 btint24cmp(int2, int4) ; ``` 需要注意的是,這里的定義"重載"了操作符策略和支持函數號:每個號在族內多次發生。 只要每個數字的實例都有不同輸入數據類型就都是允許的。輸入類型都等于操作符類的輸入類型的實例是主操作符, 并且支持該操作符類的函數,在大多數情況下應該被聲明為操作符類的一部分,而不是該族內的松散成員。 在一個B-tree操作符族內,所有的操作符都必須適當的排序,意味著傳遞法保存所有該族支持的數據類型: "if A = B and B = C, then A = C",和"if A &lt; B and B &lt; C, then A &lt; C"。 此外,代表操作符族的類型間的隱式的或二進制強制轉換必須不能改變相關的排序次序。 族內的每個操作符必須有一個支持的函數,這個函數有和操作符相同的兩個輸入數據類型。 建議一個族是完整的,也就是,對于每個數據類型的組合,所有的操作符都包括了。 每個操作符類應該只包含非交叉類型操作符和它的數據類型的支持函數。 要建立一個多數據類型散列操作符族,必須為每個該族支持的數據類型創建兼容的散列支持函數。 這里的兼容意味著函數保證對兩個通過族的相等運算符認為相等的兩個值返回相同的散列碼, 甚至兩個值屬于不容的類型時也是。當類型有不同的物理表示時這通常是很難完成的, 但是在某些情況下是可以做到的。更多的,通過隱式的或二進制強制轉換, 轉換一個操作符族中的數據類型的值到另一個同樣在操作符族中的數據類型, 必須不能改變計算散列值。注意每個數據類型只有一個支持函數,而不是每個相等操作符。 建議一個族是完整的,也就是,對于每個數據類型的組合都提供一個相等操作符。 每個操作符類應該只包含非交叉類型相等操作符和它的數據類型的支持函數。 GiST, SP-GiST, 和 GIN索引對于交叉數據類型操作符沒有任何明確的概念。 支持的操作符集對于可以處理的給定的操作符類只是主要的支持函數。 > **Note:** 在PostgreSQL 8.3之前,沒有操作符族的概念, 因此任何試圖和索引一起使用的交叉數據類型操作符必須直接綁定到索引的操作符類里面。 雖然這種方法仍然有效,但是已經棄用了,因為它使得索引的依賴太過廣泛, 并且因為當數據類型都有操作符在相同的操作符族內時,規劃器可以更有效的處理交叉數據類型比較。 ## 35.14.6\. 操作符類的系統相關性 除了是否可以用于索引外,PostgreSQL還有多種途徑使用操作符類來推斷操作符性質。 因此,即使并不打算為你自定義的數據類型在任何字段上建立索引,你可能還是希望創建操作符類。 特別是諸如`ORDER BY`和`DISTINCT`之類需要對值進行比較和排序的 SQL 特性。 要在自定義的數據類型上實現這些特性,PostgreSQL 將會為該類型查找默認的 B-tree 操作符類。該操作符類中的"equals" 成員為`GROUP BY`和`DISTINCT`定義了相等的概念, 同時操作符類的排序順序定義了默認的`ORDER BY`排序。 用戶自定義類型數組的比較同樣也依賴于默認 B-tree 操作符類定義的語意。 如果對于某個數據類型不存在默認 B-tree 操作符類,那么系統將會自動尋找默認的 Hash 操作符類。 但因為 Hash 操作符類僅僅提供相等比較,所以在實踐中它僅能用于數組的相等性測試。 如果某個數據類型不存在任何缺省操作符類,你就會在使用該 SQL 特性時得到一個類似 "could not identify an ordering operator"的錯誤。 > **Note:** PostgreSQL 7.4 以前,排序和分組操作隱含使用名為`=`, `&lt;`,`&gt;`的操作符。新的依賴默認操作符類的行為避免了對任何特定操作符名的行為的假定。 另一點重要的是一個在hash操作符族中的操作符是hash連接,hash聚合和相關優化的候選。 hash操作符族在這里是重要的,因為它標志要使用的hash函數。 ## 35.14.7\. 排序操作符 一些索引訪問方法(當前只有GIST)支持_排序操作符_的概念。 我們當前已經討論過的是_搜索操作符_。搜索操作符是可以搜索索引找到所有滿足 `WHERE` `_indexed_column_` `_operator_` `_constant_`的行。 注意,不保證將要返回的匹配行的順序。相反的,排序操作符不限制要返回的行集, 但是決定它們的順序。排序操作符是可以掃描索引以`ORDER BY` `_indexed_column_` `_operator_` `_constant_`的順序返回行。 這種方式定義排序操作符的原因是支持最近搜索,如果操作符是測量距離。例如,像這樣的查詢 ``` SELECT * FROM places ORDER BY location <-> point '(101,456)' LIMIT 10; ``` 找到一個距離給定目標點最近的點。在location字段上的GIST索引可以有效地做到這點, 因為`&lt;-&gt;`是一個排序操作符。 當搜索操作符必須返回布爾結果時,排序操作符通常返回一些其他類型,如float或numeric。 這種類型通常不同于被索引的類型。為了避免關于不同數據類型行為的硬鏈接的假設, 排序操作符的定義需要命名一個B-tree操作符族,聲明結果數據類型的排序次序。 就像前一節中闡明的,B-tree操作符族定義PostgreSQL的排序概念, 所以這是一個自然的表示。因為point `&lt;-&gt;`操作符返回`float8`, 可以在一個操作符類的創建命令中指定,像這樣: ``` OPERATOR 15 <-> (point, point) FOR ORDER BY float_ops ``` 這里的`float_ops`是包含`float8`操作的內建操作符族。 這個說明聲明了索引可以以`&lt;-&gt;`操作符的增值的順序返回行。 ## 35.14.8\. 操作符類的特殊特性 還有兩種操作符類的特殊特性沒有討論,主要是因為它們對于大多數常用的索引方法并不非常有用。 通常,把一個操作符聲明為一個操作符類(或族) 的成員意味著索引方法可以使用該操作符檢索滿足`WHERE`條件的行集合。比如: ``` SELECT * FROM table WHERE integer_column < 4; ``` 可以由一個建立在整數字段上的 B-tree 索引精確地滿足。但是有時候會有這樣的現像: 索引是用作匹配數據行的并不精確的指向。比如,如果一個 GiST 索引只為幾何對象存儲周界的方塊, 那么它就無法精確地滿足兩個非方形對象(比如多邊形)之間是否覆蓋的`WHERE`條件測試。 但是可以使用這個索引找出那些周界方塊和目標對象的周界方塊重合的對象, 然后只在索引找到的對象上做精確的重合測試。如果這種情形可以通過,那就說索引對操作符是"松散的", 松散索引搜索通過當一個行可能或可能不真正滿足查詢條件時使索引方法返回一個_recheck_ 標識來實施。核心系統將然后在檢索的行上測試原始的查詢條件,以查看是否應該作為一個合法的匹配返回。 如果索引保證返回所有要求的行加上一些附加的行,那么這種方法就可行, 這些額外的行就可以通過執行最初的操作符調用消除。支持松散搜索的索引方法(當前是GiST, SP-GiST 和 GIN) 允許個別的操作符類的支持函數設置recheck標識,所以這是本質上的一個操作符類特征。 再考慮只在索引中存儲復雜對象(比如多邊形)的周界方塊的情形。 這種情況下在索引條目里存儲整個多邊形沒有太多的數值(也可以只存儲更簡單的`box`類型對象)。 這種情形由`CREATE OPERATOR CLASS`里的`STORAGE`選項存儲。可以寫類似這樣的東西: ``` CREATE OPERATOR CLASS polygon_ops DEFAULT FOR TYPE polygon USING gist AS ... STORAGE box; ``` 目前,只有 GiST 和 GIN 索引方法支持與字段數據類型不同的`STORAGE`類型。 GiST `compress` 和 `decompress` 支持過程在使用 `STORAGE`的時候必須處理數據類型轉換。對于 GIN 來說,`STORAGE` 類型標識了"鍵"值的類型,它通常與索引字段的類型不同。比如, 一個用于整數數組字段的操作符類可能正好有整數類型的鍵。GIN `extractValue` 和`extractQuery`支持過程負責從已索引的值抽取鍵字。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看