TSM 處理常式函數會傳回一個 palloc 的 TsmRoutine
結構,其中包含指向下面描述的支援函數的指標。 大多數函數是必需的,但有些是可選的,這些指標可以為 NULL。
void SampleScanGetSampleSize (PlannerInfo *root, RelOptInfo *baserel, List *paramexprs, BlockNumber *pages, double *tuples);
此函數在規劃期間被呼叫。 它必須估計在樣本掃描期間將讀取的關聯頁面數量,以及掃描將選擇的元組數量。(例如,這些可以透過估計抽樣比例來確定,然後將 baserel->pages
和 baserel->tuples
數字乘以該比例,確保將結果四捨五入為整數值。)paramexprs
清單包含作為 TABLESAMPLE
子句參數的表達式。建議使用 estimate_expression_value()
來嘗試將這些表達式簡化為常數(如果需要它們的值來進行估計);但即使無法簡化它們,該函數也必須提供大小估計值,即使這些值看起來無效也不應失敗(請記住,它們只是執行時間值的估計值)。 pages
和 tuples
參數是輸出。
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)
為 true 時,實際不會執行掃描,因此此函數應僅執行使節點狀態對於 EXPLAIN
和 EndSampleScan
有效所需的最小操作。
此函數可以省略(將指標設定為 NULL),在這種情況下,BeginSampleScan
必須執行採樣方法所需的所有初始化。
void BeginSampleScan (SampleScanState *node, Datum *params, int nparams, uint32 seed);
開始執行抽樣掃描。 這在第一次嘗試提取元組之前被呼叫,如果需要重新啟動掃描,則可以再次呼叫。 關於要掃描的表的信息可以透過 SampleScanState
節點的欄位訪問(但請注意,node->ss.ss_currentScanDesc
掃描描述符尚未設定)。 長度為 nparams
的 params
陣列包含在 TABLESAMPLE
子句中提供的參數值。 這些將具有採樣方法的 parameterTypes
清單中指定的數字和類型,並且已經過檢查以確保不為 null。 seed
包含用於在採樣方法中產生的任何隨機數的種子; 如果給定了 REPEATABLE
值,則它是從該值衍生的雜湊值,否則它是 random()
的結果。
此函數可以調整欄位 node->use_bulkread
和 node->use_pagemode
。 如果 node->use_bulkread
為 true
(預設值),則掃描將使用一種緩衝區訪問策略,該策略鼓勵在使用後回收緩衝區。 如果掃描僅訪問表頁面的一小部分,則將其設定為 false
可能是合理的。 如果 node->use_pagemode
為 true
(預設值),則掃描將對每個訪問頁面上的所有元組執行單次通過的可見性檢查。 如果掃描僅選擇每個訪問頁面上元組的一小部分,則將其設定為 false
可能是合理的。 這將導致執行較少的元組可見性檢查,但由於它需要更多的鎖定,因此每個檢查將會更加昂貴。
如果採樣方法被標記為 repeatable_across_scans
,則它必須能夠在重新掃描期間選擇與原始掃描相同的元組集合,也就是說,對 BeginSampleScan
的全新呼叫必須導致選擇與之前相同的元組(如果 TABLESAMPLE
參數和種子沒有改變)。
BlockNumber NextSampleBlock (SampleScanState *node, BlockNumber nblocks);
傳回要掃描的下一個頁面的區塊編號,如果沒有頁面要掃描,則傳回 InvalidBlockNumber
。
此函數可以省略(將指標設定為 NULL),在這種情況下,核心程式碼將執行整個關聯的循序掃描。 這種掃描可以使用同步掃描,因此採樣方法不能假設關聯頁面在每次掃描中都以相同的順序訪問。
OffsetNumber NextSampleTuple (SampleScanState *node, BlockNumber blockno, OffsetNumber maxoffset);
傳回要在指定頁面上抽樣的下一個元組的偏移量編號,如果沒有元組要抽樣,則傳回 InvalidOffsetNumber
。 maxoffset
是頁面上使用的最大偏移量編號。
沒有明確告知 NextSampleTuple
在 1 .. maxoffset
範圍內的哪個偏移量編號實際包含有效的元組。 這通常不是問題,因為核心程式碼會忽略對遺失或不可見元組進行抽樣的請求; 這不應導致樣本中出現任何偏差。 但是,如果需要,該函數可以使用 node->donetuples
來檢查它傳回的元組中有多少是有效且可見的。
NextSampleTuple
必須 不 假設 blockno
是最近一次 NextSampleBlock
呼叫傳回的相同頁面編號。 它是由先前的 NextSampleBlock
呼叫傳回的,但核心程式碼可以提前呼叫 NextSampleBlock
,以便在實際掃描頁面之前,從而支援預取。 可以假設一旦開始抽樣給定的頁面,後續的 NextSampleTuple
呼叫都引用相同的頁面,直到傳回 InvalidOffsetNumber
。
void EndSampleScan (SampleScanState *node);
結束掃描並釋放資源。通常釋放 palloc 分配的記憶體並不重要,但任何外部可見的資源都應清理乾淨。在沒有此類資源的常見情況下,可以省略此函數(將指標設置為 NULL)。
如果您在文件中發現任何不正確、與您使用特定功能的經驗不符或需要進一步澄清之處,請使用此表格來報告文件問題。