2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5

59.1. 取樣方法支援函式 #

TSM 處理函式返回一個 palloc 分配的 TsmRoutine 結構,其中包含指向下面描述的支援函式的指標。大多數函式是必需的,但有些是可選的,這些指標可以為 NULL。

void
SampleScanGetSampleSize (PlannerInfo *root,
                         RelOptInfo *baserel,
                         List *paramexprs,
                         BlockNumber *pages,
                         double *tuples);

此函式在規劃期間被呼叫。它必須估計在抽樣掃描期間將讀取的表頁數,以及掃描將選擇的元組數。(例如,這可以透過估計取樣分數,然後將 baserel->pagesbaserel->tuples 數字乘以該分數來確定,確保將結果四捨五入為整數值。)paramexprs 列表包含 TABLESAMPLE 子句的引數表示式。如果需要表示式的值進行估算,建議使用 estimate_expression_value() 將這些表示式簡化為常量;但是,即使它們無法被簡化,該函式也必須提供大小估算,並且即使值看起來無效也不應失敗(請記住,它們只是對執行時值的估算)。pagestuples 引數是輸出引數。

void
InitSampleScan (SampleScanState *node,
                int eflags);

為 SampleScan 計劃節點執行初始化。這在執行器啟動期間被呼叫。它應該在處理開始之前執行所有必要的初始化。SampleScanState 節點已經建立,但其 tsm_state 欄位為 NULL。InitSampleScan 函式可以 palloc 任何取樣方法所需的內部狀態資料,並將其指標儲存在 node->tsm_state 中。有關要掃描的表的資訊可以透過 SampleScanState 節點的其他欄位訪問(但請注意,node->ss.ss_currentScanDesc 掃描描述符尚未設定)。eflags 包含描述此計劃節點執行器操作模式的標誌位。

(eflags & EXEC_FLAG_EXPLAIN_ONLY) 為真時,實際上不會執行掃描,因此此函式僅應執行最少的操作,以使節點狀態對於 EXPLAINEndSampleScan 有效。

此函式可以省略(將指標設定為 NULL),在這種情況下,BeginSampleScan 必須執行取樣方法所需的所有初始化。

void
BeginSampleScan (SampleScanState *node,
                 Datum *params,
                 int nparams,
                 uint32 seed);

開始執行取樣掃描。這在嘗試獲取第一個元組之前被呼叫,並且在掃描需要重新啟動時可能會再次被呼叫。有關要掃描的表的資訊可以透過 SampleScanState 節點的欄位訪問(但請注意,node->ss.ss_currentScanDesc 掃描描述符尚未設定)。params 陣列(長度為 nparams)包含 TABLESAMPLE 子句中提供的引數的值。它們將具有采樣方法的 parameterTypes 列表中指定的數量和型別,並且已經過檢查,不為 NULL。seed 包含用於取樣方法中生成的任何隨機數的種子;如果提供了 REPEATABLE 值,則它是從該值派生的雜湊,否則它是 random() 的結果。

此函式可以調整 node->use_bulkreadnode->use_pagemode 欄位。如果 node->use_bulkreadtrue(預設值),則掃描將使用鼓勵在使用後回收緩衝區的緩衝區訪問策略。如果掃描只訪問表的一小部分頁面,則將此設定為 false 可能是合理的。如果 node->use_pagemodetrue(預設值),則掃描將在所有訪問的頁面上對所有元組進行單次可見性檢查。如果掃描只選擇每訪問頁面上的一小部分元組,則將此設定為 false 可能是合理的。這將導致執行的元組可見性檢查次數更少,儘管每次檢查的成本更高,因為它需要更多的鎖定。

如果取樣方法被標記為 repeatable_across_scans,那麼它必須能夠在重新掃描時選擇與原始掃描相同的元組集,也就是說,在 BeginSampleScan 被重新呼叫後,必須選擇與之前相同的元組(如果 TABLESAMPLE 引數和種子沒有改變)。

BlockNumber
NextSampleBlock (SampleScanState *node, BlockNumber nblocks);

返回下一個要掃描的頁的塊號,如果沒有剩餘的頁要掃描,則返回 InvalidBlockNumber

此函式可以省略(將指標設定為 NULL),在這種情況下,核心程式碼將對整個關係執行順序掃描。這種掃描可以使用同步掃描,因此取樣方法不能假定關係頁面在每次掃描時都以相同的順序訪問。

OffsetNumber
NextSampleTuple (SampleScanState *node,
                 BlockNumber blockno,
                 OffsetNumber maxoffset);

返回指定頁面上下一個要取樣的元組的偏移號,如果沒有剩餘的元組要取樣,則返回 InvalidOffsetNumbermaxoffset 是頁面上使用的最大偏移號。

注意

NextSampleTuple 沒有明確知道 1 .. maxoffset 範圍內的哪些偏移量實際包含有效元組。這通常不是問題,因為核心程式碼會忽略對缺失或不可見元組的取樣請求;這不應導致樣本出現任何偏差。但是,如果需要,該函式可以使用 node->donetuples 來檢查它返回的元組中有多少是有效的和可見的。

注意

NextSampleTuple 不能 假定 blockno 是上一次 NextSampleBlock 呼叫返回的相同頁面號。它是從之前的某個 NextSampleBlock 呼叫返回的,但核心程式碼允許在實際掃描頁面之前預先呼叫 NextSampleBlock,以支援預取。可以假定一旦開始對某個頁面進行取樣, successive NextSampleTuple 呼叫都將引用同一個頁面,直到返回 InvalidOffsetNumber

void
EndSampleScan (SampleScanState *node);

結束掃描並釋放資源。通常不需要釋放 palloc 分配的記憶體,但任何外部可見的資源都應被清理。此函式可以省略(將指標設定為 NULL),在通常情況下,沒有此類資源。

提交更正

如果您在文件中發現任何不正確、不符合您使用該特定功能時的經驗或需要進一步說明的內容,請使用 此表單 報告文件問題。