支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5

64.5. BRIN 索引 #

64.5.1. 簡介 #

BRIN代表 Block Range Index(區塊範圍索引)。BRIN設計用於處理大型表格,其中某些欄位與其在表格中的實體位置具有某些自然相關性。

BRIN區塊範圍(或頁面範圍)運作。區塊範圍是表格中實體相鄰的一組頁面;對於每個區塊範圍,索引會儲存一些摘要資訊。例如,儲存商店銷售訂單的表格可能有一個日期欄位,記錄每個訂單的下訂日期,並且大部分時間,較早訂單的條目也會較早出現在表格中;儲存郵遞區號欄位的表格可能將一個城市的所有區號自然地分組在一起。

BRIN索引可以透過常規的位元圖索引掃描來滿足查詢,如果索引儲存的摘要資訊與查詢條件一致,則會傳回每個範圍內所有頁面中的所有元組。查詢執行器負責重新檢查這些元組並丟棄不符合查詢條件的元組 — 換句話說,這些索引是有損的。因為一個BRIN索引非常小,所以掃描索引與循序掃描相比,增加的額外開銷很小,但可以避免掃描已知不包含符合元組的表格的較大部份。

一個BRIN索引將儲存的特定資料,以及索引能夠滿足的特定查詢,取決於為索引的每個欄位選擇的運算子類別。例如,具有線性排序順序的資料類型可以擁有運算子類別,該類別儲存每個區塊範圍內的最小值和最大值;幾何類型可能會儲存區塊範圍內所有物件的邊界框。

區塊範圍的大小在建立索引時由 pages_per_range 儲存參數決定。索引條目的數量將等於關係的大小(以頁為單位)除以 pages_per_range 的選定值。因此,數字越小,索引越大(因為需要儲存更多索引條目),但同時儲存的摘要資料可以更精確,並且在索引掃描期間可以跳過更多資料區塊。

64.5.1.1. 索引維護 #

在建立時,會掃描所有現有的堆積頁面,並為每個範圍建立摘要索引元組,包括最後可能不完整的範圍。隨著新頁面被資料填滿,已經摘要化的頁面範圍會導致摘要資訊使用來自新元組的資料進行更新。當建立一個不屬於最後摘要範圍的新頁面時,新頁面所屬的範圍不會自動取得摘要元組;這些元組在稍後呼叫摘要執行之前,保持未摘要化,從而建立該範圍的初始摘要。

有多種方法可以觸發頁面範圍的初始摘要化。如果表格被清理,無論是手動還是由自動清理,所有現有的未摘要化頁面範圍都會被摘要化。此外,如果索引的 autosummarize 參數已啟用(預設情況下未啟用),則每當自動清空在該資料庫中執行時,都會針對所有已填滿的未摘要化頁面範圍執行摘要化,無論表格本身是否由自動清理處理;請參閱下文。

最後,可以使用以下函數(在這些函數執行時,search_path 暫時變更為 pg_catalog, pg_temp):

brin_summarize_new_values(regclass),它會摘要所有未摘要化的範圍;
brin_summarize_range(regclass, bigint),如果範圍未摘要化,它只會摘要包含給定頁面的範圍。

當啟用自動摘要化時,系統會向 autovacuum 發送請求,以便在偵測到下一個區塊範圍的第一個頁面的第一個項目插入時,對區塊範圍執行有目標的摘要化,以便在下次自動清理工作程序在同一個資料庫中完成執行時完成。如果請求佇列已滿,則不會記錄請求,並且會將訊息傳送到伺服器日誌。

LOG:  request for BRIN range summarization for index "brin_wi_idx" page 128 was not recorded

發生這種情況時,範圍將保持未摘要化,直到對表格進行下一次常規清理執行,或呼叫上述函數之一。

相反地,可以使用 brin_desummarize_range(regclass, bigint) 函數取消範圍的摘要化,當索引元組不再是一個非常好的表示時,因為現有值已變更,此函數非常有用。有關詳細資訊,請參閱第 9.28.8 節

64.5.2. 內建運算子類別 #

核心 PostgreSQL 發行版本包含BRIN表 64.4 中所示的運算子類別。

minmax 運算子類別會儲存範圍內索引欄位中出現的最小值和最大值。inclusion 運算子類別會儲存一個值,該值包含範圍內索引欄位中的值。bloom 運算子類別會為範圍內的所有值建立 Bloom 篩選器。minmax-multi 運算子類別會儲存多個最小值和最大值,表示範圍內索引欄位中出現的值。

表 64.4. 內建BRIN運算子類別

名稱 可索引運算子
bit_minmax_ops = (bit,bit)
< (bit,bit)
> (bit,bit)
<= (bit,bit)
>= (bit,bit)
box_inclusion_ops @> (box,point)
<< (box,box)
&< (box,box)
&> (box,box)
>> (box,box)
<@ (box,box)
@> (盒,盒)
~= (盒,盒)
&& (盒,盒)
<<| (盒,盒)
&<| (盒,盒)
|&> (盒,盒)
|>> (盒,盒)
bpchar_bloom_ops = (字元,字元)
bpchar_minmax_ops = (字元,字元)
< (字元,字元)
<= (字元,字元)
> (字元,字元)
>= (字元,字元)
bytea_bloom_ops = (bytea,bytea)
bytea_minmax_ops = (bytea,bytea)
< (bytea,bytea)
<= (bytea,bytea)
> (bytea,bytea)
>= (bytea,bytea)
char_bloom_ops = ("char","char")
char_minmax_ops = ("char","char")
< ("char","char")
<= ("char","char")
> ("char","char")
>= ("char","char")
date_bloom_ops = (日期,日期)
date_minmax_ops = (日期,日期)
< (日期,日期)
<= (日期,日期)
> (日期,日期)
>= (日期,日期)
date_minmax_multi_ops = (日期,日期)
< (日期,日期)
<= (日期,日期)
> (日期,日期)
>= (日期,日期)
float4_bloom_ops = (float4,float4)
float4_minmax_ops = (float4,float4)
< (float4,float4)
> (float4,float4)
<= (float4,float4)
>= (float4,float4)
float4_minmax_multi_ops = (float4,float4)
< (float4,float4)
> (float4,float4)
<= (float4,float4)
>= (float4,float4)
float8_bloom_ops = (float8,float8)
float8_minmax_ops = (float8,float8)
< (float8,float8)
<= (float8,float8)
> (float8,float8)
>= (float8,float8)
float8_minmax_multi_ops = (float8,float8)
< (float8,float8)
<= (float8,float8)
> (float8,float8)
>= (float8,float8)
inet_inclusion_ops << (inet,inet)
<<= (inet,inet)
>> (inet,inet)
>>= (inet,inet)
= (inet,inet)
&& (inet,inet)
inet_bloom_ops = (inet,inet)
inet_minmax_ops = (inet,inet)
< (inet,inet)
<= (inet,inet)
> (inet,inet)
>= (inet,inet)
inet_minmax_multi_ops = (inet,inet)
< (inet,inet)
<= (inet,inet)
> (inet,inet)
>= (inet,inet)
int2_bloom_ops = (int2,int2)
int2_minmax_ops = (int2,int2)
< (int2,int2)
> (int2,int2)
<= (int2,int2)
>= (int2,int2)
int2_minmax_multi_ops = (int2,int2)
< (int2,int2)
> (int2,int2)
<= (int2,int2)
>= (int2,int2)
int4_bloom_ops = (int4,int4)
int4_minmax_ops = (int4,int4)
< (int4,int4)
> (int4,int4)
<= (int4,int4)
>= (int4,int4)
int4_minmax_multi_ops = (int4,int4)
< (int4,int4)
> (int4,int4)
<= (int4,int4)
>= (int4,int4)
int8_bloom_ops = (bigint,bigint)
int8_minmax_ops = (bigint,bigint)
< (bigint,bigint)
> (bigint,bigint)
<= (bigint,bigint)
>= (bigint,bigint)
int8_minmax_multi_ops = (bigint,bigint)
< (bigint,bigint)
> (bigint,bigint)
<= (bigint,bigint)
>= (bigint,bigint)
interval_bloom_ops = (interval,interval)
interval_minmax_ops = (interval,interval)
< (interval,interval)
<= (interval,interval)
> (interval,interval)
>= (interval,interval)
interval_minmax_multi_ops = (interval,interval)
< (interval,interval)
<= (interval,interval)
> (interval,interval)
>= (interval,interval)
macaddr_bloom_ops = (macaddr,macaddr)
macaddr_minmax_ops = (macaddr,macaddr)
< (macaddr,macaddr)
<= (macaddr,macaddr)
> (macaddr,macaddr)
>= (macaddr,macaddr)
macaddr_minmax_multi_ops = (macaddr,macaddr)
< (macaddr,macaddr)
<= (macaddr,macaddr)
> (macaddr,macaddr)
>= (macaddr,macaddr)
macaddr8_bloom_ops = (macaddr8,macaddr8)
macaddr8_minmax_ops = (macaddr8,macaddr8)
< (macaddr8,macaddr8)
<= (macaddr8,macaddr8)
> (macaddr8,macaddr8)
>= (macaddr8,macaddr8)
macaddr8_minmax_multi_ops = (macaddr8,macaddr8)
< (macaddr8,macaddr8)
<= (macaddr8,macaddr8)
> (macaddr8,macaddr8)
>= (macaddr8,macaddr8)
name_bloom_ops = (name,name)
name_minmax_ops = (name,name)
< (name,name)
<= (name,name)
> (name,name)
>= (name,name)
numeric_bloom_ops = (numeric,numeric)
numeric_minmax_ops = (numeric,numeric)
< (numeric,numeric)
<= (numeric,numeric)
> (numeric,numeric)
>= (numeric,numeric)
numeric_minmax_multi_ops = (numeric,numeric)
< (numeric,numeric)
<= (numeric,numeric)
> (numeric,numeric)
>= (numeric,numeric)
oid_bloom_ops = (oid,oid)
oid_minmax_ops = (oid,oid)
< (oid,oid)
> (oid,oid)
<= (oid,oid)
>= (oid,oid)
oid_minmax_multi_ops = (oid,oid)
< (oid,oid)
> (oid,oid)
<= (oid,oid)
>= (oid,oid)
pg_lsn_bloom_ops = (pg_lsn,pg_lsn)
pg_lsn_minmax_ops = (pg_lsn,pg_lsn)
< (pg_lsn,pg_lsn)
> (pg_lsn,pg_lsn)
<= (pg_lsn,pg_lsn)
>= (pg_lsn,pg_lsn)
pg_lsn_minmax_multi_ops = (pg_lsn,pg_lsn)
< (pg_lsn,pg_lsn)
> (pg_lsn,pg_lsn)
<= (pg_lsn,pg_lsn)
>= (pg_lsn,pg_lsn)
range_inclusion_ops = (anyrange,anyrange)
< (anyrange,anyrange)
<= (anyrange,anyrange)
>= (anyrange,anyrange)
> (anyrange,anyrange)
&& (anyrange,anyrange)
@> (anyrange,anyelement)
@> (anyrange,anyrange)
<@ (anyrange,anyrange)
<< (anyrange,anyrange)
>> (anyrange,anyrange)
&< (anyrange,anyrange)
&> (anyrange,anyrange)
-|- (anyrange,anyrange)
text_bloom_ops = (文字,文字)
text_minmax_ops = (文字,文字)
< (文字,文字)
<= (文字,文字)
> (文字,文字)
>= (文字,文字)
tid_bloom_ops = (tid,tid)
tid_minmax_ops = (tid,tid)
< (tid,tid)
> (tid,tid)
<= (tid,tid)
>= (tid,tid)
tid_minmax_multi_ops = (tid,tid)
< (tid,tid)
> (tid,tid)
<= (tid,tid)
>= (tid,tid)
timestamp_bloom_ops = (時間戳記,時間戳記)
timestamp_minmax_ops = (時間戳記,時間戳記)
< (時間戳記,時間戳記)
<= (時間戳記,時間戳記)
> (時間戳記,時間戳記)
>= (時間戳記,時間戳記)
timestamp_minmax_multi_ops = (時間戳記,時間戳記)
< (時間戳記,時間戳記)
<= (時間戳記,時間戳記)
> (時間戳記,時間戳記)
>= (時間戳記,時間戳記)
timestamptz_bloom_ops = (含時區時間戳記,含時區時間戳記)
timestamptz_minmax_ops = (含時區時間戳記,含時區時間戳記)
< (含時區時間戳記,含時區時間戳記)
<= (含時區時間戳記,含時區時間戳記)
> (含時區時間戳記,含時區時間戳記)
>= (含時區時間戳記,含時區時間戳記)
timestamptz_minmax_multi_ops = (含時區時間戳記,含時區時間戳記)
< (含時區時間戳記,含時區時間戳記)
<= (含時區時間戳記,含時區時間戳記)
> (含時區時間戳記,含時區時間戳記)
>= (含時區時間戳記,含時區時間戳記)
time_bloom_ops = (時間,時間)
time_minmax_ops = (時間,時間)
< (時間,時間)
<= (時間,時間)
> (時間,時間)
>= (時間,時間)
time_minmax_multi_ops = (時間,時間)
< (時間,時間)
<= (時間,時間)
> (時間,時間)
>= (時間,時間)
timetz_bloom_ops = (含時區時間,含時區時間)
timetz_minmax_ops = (含時區時間,含時區時間)
< (含時區時間,含時區時間)
<= (含時區時間,含時區時間)
> (含時區時間,含時區時間)
>= (含時區時間,含時區時間)
timetz_minmax_multi_ops = (含時區時間,含時區時間)
< (含時區時間,含時區時間)
<= (含時區時間,含時區時間)
> (含時區時間,含時區時間)
>= (含時區時間,含時區時間)
uuid_bloom_ops = (uuid,uuid)
uuid_minmax_ops = (uuid,uuid)
< (uuid,uuid)
> (uuid,uuid)
<= (uuid,uuid)
>= (uuid,uuid)
uuid_minmax_multi_ops = (uuid,uuid)
< (uuid,uuid)
> (uuid,uuid)
<= (uuid,uuid)
>= (uuid,uuid)
varbit_minmax_ops = (varbit,varbit)
< (varbit,varbit)
> (varbit,varbit)
<= (varbit,varbit)
>= (varbit,varbit)

64.5.2.1. 運算子類別參數 #

某些內建的運算子類別允許指定影響運算子類別行為的參數。每個運算子類別都有自己的一組允許參數。只有 bloomminmax-multi 運算子類別允許指定參數。

bloom 運算子類別接受以下參數:

n_distinct_per_range

定義區塊範圍中不同非空值的估計數量,由BRINbloom 索引用於調整 Bloom 篩選器的大小。它的行為類似於 ALTER TABLEn_distinct 選項。當設定為正值時,每個區塊範圍都假定包含此數量的不同非空值。當設定為負值時(必須大於或等於 -1),不同非空值的數量假定與區塊範圍中可能的最大元組數量(每個區塊約 290 列)成線性增長。預設值為 -0.1,且不同非空值的最小數量為 16

false_positive_rate

定義所需的假陽性率,由BRINbloom 索引用於調整 Bloom 篩選器的大小。該值必須介於 0.0001 和 0.25 之間。預設值為 0.01,即 1% 的假陽性率。

minmax-multi 運算子類別接受以下參數:

values_per_range

定義由BRINminmax 索引儲存的最大值數量,以總結一個區塊範圍。每個值可以代表一個點,也可以代表一個區間的邊界。值必須介於 8 和 256 之間,預設值為 32。

64.5.3. 可擴充性 #

BRIN介面具有高度的抽象性,僅要求存取方法實作者實現所存取資料類型的語義即可。該BRINlayer 本身會處理並行、日誌記錄和搜尋索引結構。

要讓一個BRIN存取方法運作,只需要實作幾個使用者定義的方法,這些方法定義了儲存在索引中的摘要值的行為,以及它們與掃描鍵互動的方式。簡而言之,BRIN結合了可擴展性、通用性、程式碼重用和清晰的介面。

一個 operator class 為了BRIN必須提供四個方法

BrinOpcInfo *opcInfo(Oid type_oid)

傳回關於被索引欄位摘要資料的內部資訊。 傳回值必須指向一個 palloc 配置的 BrinOpcInfo,其定義如下:

typedef struct BrinOpcInfo
{
    /* Number of columns stored in an index column of this opclass */
    uint16      oi_nstored;

    /* Opaque pointer for the opclass' private use */
    void       *oi_opaque;

    /* Type cache entries of the stored columns */
    TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER];
} BrinOpcInfo;

BrinOpcInfo.oi_opaque 可以被 operator class 的常式用來在索引掃描期間傳遞支援函式之間的資訊。

bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey *keys, int nkeys)

傳回所有 ScanKey 條目是否與給定範圍的索引值一致。要使用的屬性編號作為掃描鍵的一部分傳遞。可以一次傳遞同一屬性的多個掃描鍵;條目的數量由 nkeys 參數決定。

bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey key)

傳回 ScanKey 是否與給定範圍的索引值一致。要使用的屬性編號作為掃描鍵的一部分傳遞。這是 consistent 函式的一個較舊的向後相容變體。

bool addValue(BrinDesc *bdesc, BrinValues *column, Datum newval, bool isnull)

給定一個索引元組和一個被索引的值,修改元組的指示屬性,以便它額外表示新的值。如果對元組進行了任何修改,則傳回 true

bool unionTuples(BrinDesc *bdesc, BrinValues *a, BrinValues *b)

合併兩個索引元組。給定兩個索引元組,修改其中第一個元組的指示屬性,以便它表示兩個元組。第二個元組不被修改。

一個 operator class 為了BRIN可以選擇性地指定以下方法

void options(local_relopts *relopts)

定義一組使用者可見的參數,用於控制 operator class 的行為。

options 函式會傳遞一個指向 local_relopts 結構的指標,該結構需要填寫一組特定於 operator class 的選項。可以使用 PG_HAS_OPCLASS_OPTIONS()PG_GET_OPCLASS_OPTIONS() 巨集從其他支援函式存取這些選項。

由於索引值的鍵提取和鍵在BRIN中的表示都具有彈性,它們可能會取決於使用者指定的參數。

核心發行版包含對四種類型 operator class 的支援:minmax、minmax-multi、inclusion 和 bloom。使用它們的 operator class 定義已針對核心資料類型進行了適當的發布。使用者可以使用等效的定義為其他資料類型定義額外的 operator class,而無需編寫任何原始碼;宣告適當的目錄條目就足夠了。請注意,關於運算子策略語義的假設已嵌入到支援函式的原始碼中。

如果編寫上述四個主要支援函式的實作,也可以使用實作完全不同語義的 operator class。請注意,不保證跨主要版本的向後相容性:例如,在以後的版本中可能需要額外的支援函式。

要為實現完全有序集合的資料類型編寫 operator class,可以使用 minmax 支援函式以及對應的運算子,如表 64.5所示。 所有 operator class 成員(函式和運算子)都是強制性的。

表 64.5. Minmax Operator Class 的函式和支援編號

Operator class 成員 物件
支援函式 1 內部函式 brin_minmax_opcinfo()
支援函式 2 內部函式 brin_minmax_add_value()
支援函式 3 內部函式 brin_minmax_consistent()
支援函式 4 內部函式 brin_minmax_union()
運算子策略 1 運算子 小於
運算子策略 2 運算子 小於或等於
運算子策略 3 運算子 等於
運算子策略 4 運算子 大於或等於
運算子策略 5 運算子 大於

要為複雜資料類型編寫 operator class,該資料類型具有包含在另一個類型中的值,可以使用 inclusion 支援函式以及對應的運算子,如表 64.6所示。 它只需要一個額外的函式,該函式可以用任何語言編寫。 可以定義更多函式以實現其他功能。 所有運算子都是可選的。 某些運算子需要其他運算子,如表中的相依性所示。

表 64.6. Inclusion Operator Class 的函式和支援編號

Operator class 成員 物件 相依性
支援函式 1 內部函式 brin_inclusion_opcinfo()  
支援函式 2 內部函式 brin_inclusion_add_value()  
支援函式 3 內部函式 brin_inclusion_consistent()  
支援函式 4 內部函式 brin_inclusion_union()  
支援函式 11 用於合併兩個元素的函式  
支援函式 12 可選函式,用於檢查兩個元素是否可以合併  
支援函式 13 可選函式,用於檢查一個元素是否包含在另一個元素中  
支援函式 14 可選函式,用於檢查元素是否為空  
運算子策略 1 運算子 左側 運算子策略 4
運算子策略 2 運算子 不延伸到右側 運算子策略 5
運算子策略 3 運算子 重疊  
運算子策略 4 運算子 不延伸到左側 運算子策略 1
運算子策略 5 運算子 右側 運算子策略 2
運算子策略 6, 18 運算子 相同或等於 運算子策略 7
運算子策略 7, 16, 24, 25 運算子 包含或等於  
運算子策略 8, 26, 27 運算子 被包含於或等於 運算子策略 3
運算子策略 9 運算子 不向上延伸 運算子策略 11
運算子策略 10 運算子 低於 運算子策略 12
運算子策略 11 運算子 高於 運算子策略 9
運算子策略 12 運算子 不向下延伸 運算子策略 10
運算子策略 20 運算子 小於 運算子策略 5
運算子策略 21 運算子 小於或等於 運算子策略 5
運算子策略 22 運算子 大於 運算子策略 1
運算子策略 23 運算子 大於或等於 運算子策略 1

支援函數編號 1 到 10 保留給 BRIN 內部函數使用,因此 SQL 層級的函數從編號 11 開始。支援函數編號 11 是建立索引所需的主要函數。它應該接受兩個與運算子類別具有相同資料類型的參數,並傳回它們的聯集。如果包含運算子類別是使用 STORAGE 參數定義的,它可以儲存具有不同資料類型的聯集值。聯集函數的傳回值應與 STORAGE 資料類型相符。

提供支援函數編號 12 和 14 以支援內建資料類型的不規則性。函數編號 12 用於支援來自不同系列的網路位址,這些位址不可合併。函數編號 14 用於支援空範圍。函數編號 13 是一個可選但建議使用的函數,它允許在將新值傳遞給聯集函數之前檢查該值。由於 BRIN 框架可以在聯集未更改時捷徑某些操作,因此使用此函數可以提高索引效能。

要為僅實現相等運算子並支援雜湊的資料類型編寫運算子類別,可以使用 bloom 支援程序以及相應的運算子,如表 64.7所示。所有運算子類別成員(程序和運算子)都是強制性的。

表 64.7. Bloom 運算子類別的程序和支援編號

Operator class 成員 物件
支援程序 1 內部函數 brin_bloom_opcinfo()
支援程序 2 內部函數 brin_bloom_add_value()
支援程序 3 內部函數 brin_bloom_consistent()
支援程序 4 內部函數 brin_bloom_union()
支援程序 5 內部函數 brin_bloom_options()
支援程序 11 計算元素雜湊值的函數
運算子策略 1 運算子 等於

支援程序編號 1-10 保留給 BRIN 內部函數使用,因此 SQL 層級的函數從編號 11 開始。支援函數編號 11 是建立索引所需的主要函數。它應該接受一個與運算子類別具有相同資料類型的參數,並傳回該值的雜湊值。

minmax-multi 運算子類別也適用於實現完全有序集合的資料類型,並且可以看作是 minmax 運算子類別的簡單擴展。雖然 minmax 運算子類別將每個區塊範圍的值總結為單個連續區間,但 minmax-multi 允許總結為多個較小的區間,以改善對異常值的處理。可以使用 minmax-multi 支援程序以及相應的運算子,如表 64.8所示。所有運算子類別成員(程序和運算子)都是強制性的。

表 64.8. minmax-multi 運算子類別的程序和支援編號

Operator class 成員 物件
支援程序 1 內部函數 brin_minmax_multi_opcinfo()
支援程序 2 內部函數 brin_minmax_multi_add_value()
支援程序 3 內部函數 brin_minmax_multi_consistent()
支援程序 4 內部函數 brin_minmax_multi_union()
支援程序 5 內部函數 brin_minmax_multi_options()
支援程序 11 計算兩個值之間距離的函數(範圍長度)
運算子策略 1 運算子 小於
運算子策略 2 運算子 小於或等於
運算子策略 3 運算子 等於
運算子策略 4 運算子 大於或等於
運算子策略 5 運算子 大於

minmax 和 inclusion 運算子類別都支援跨資料類型的運算子,儘管如此,它們的依賴關係變得更加複雜。 minmax 運算子類別要求定義一整組運算子,且兩個參數都具有相同的資料類型。它允許透過定義額外的運算子集合來支援其他資料類型。inclusion 運算子類別運算子策略依賴於另一個運算子策略,如表 64.6所示,或與自身相同的運算子策略。它們要求依賴運算子定義為具有 STORAGE 資料類型作為左側參數,而另一個支援的資料類型是支援運算子的右側參數。請參閱 float4_minmax_ops 作為 minmax 的範例,以及 box_inclusion_ops 作為 inclusion 的範例。

提交更正

如果您在文件中發現任何不正確、與您的特定功能使用經驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。