Вспомогательные функции метода выборки
Функция-обработчик TSM возвращает структуру TsmRoutine
(выделенную вызовом palloc), содержащую указатели на вспомогательные функции, описанные ниже. Большинство функций являются обязательными, но некоторые - необязательными, и эти указатели могут быть NULL.
void
SampleScanGetSampleSize (PlannerInfo *root,
RelOptInfo *baserel,
List *paramexprs,
BlockNumber *pages,
double *tuples);
Эта функция вызывается во время планирования. Она должна оценить количество страниц отношений, которые будут прочитаны во время выборочного сканирования, и количество кортежей, которые будут выбраны при сканировании. (Например, их можно определить, оценив долю выборки, а затем умножив на нее числа baserel->pages
и baserel->tuples
, не забыв округлить результаты до целых значений). Список paramexprs
содержит выражение(я), являющиеся параметрами предложен ия TABLESAMPLE
. Рекомендуется использовать функцию estimate_expression_value()
, чтобы попытаться свести эти выражения к константам, если их значения нужны для оценки; но функция должна предоставлять оценки размера, даже если их нельзя свести, и не должна выходить из строя, даже если значения кажутся недостоверными (помните, что это только оценки того, какими будут значения во время выполнения). Параметры страниц и кортежей являются выходными данными.
void
InitSampleScan (SampleScanState *node,
int eflags);
Инициализация для выполнения узла плана SampleScan
. Вызывается во время запуска исполнителя. Он должен выполнить любую инициализацию, необходимую перед началом обработки. Узел SampleScanState
уже создан, но его поле tsm_state
равно NULL. Функция InitSampleScan
может выделить все внутренние данные состояния, необходимые методу выборки, и сохранить указатель на них в node->tsm_state
. Информация о сканируемой таблице доступна через другие поля узла SampleScanState
(но обратите внимание, что дескриптор сканирования node->ss.ss_currentScanDesc
еще не установлен). eflags
содержит биты флагов, описывающие режим работы исполнителя для данного узла плана.
Когда (eflags & EXEC_FLAG_EXPLAIN_ONLY
) является истиной, сканирование фактически не будет выполнено, поэтому эта функция должна выполнять только минимум действий, необходимых для того, чтобы состояние узла было пригодно для EXPLAIN
и EndSampleScan
.
Эту функцию можно не использовать (установить указатель на 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_bulkread
и node->use_pagemode
. Если node->use_bulkread
равно true
, что по умолчанию, то сканирование будет использовать стратегию доступа к буферам, которая поощряет переработку буферов после использования. Может быть разумно установить значение false
, если сканирование будет посещать только небольшую часть страниц таблицы. Если node->use_pagemode
имеет значение true
, что и происходит по умолчанию, сканирование будет выполнять проверку видимости за один проход для всех кортежей на каждой посещенной странице. Может быть разумно установить значение false
, если сканирование будет выбирать только небольшую часть кортежей на каждой посещенной странице. В этом случае будет выполняться меньше проверок видимости кортежей, хотя каждая из них будет более дорогостоящей, поскольку потребует больше блокировок.
Если метод выборки помечен как repeatable_across_scans
, он должен быть способен выбрать тот же набор кортежей при повторном сканировании, что и первоначально, то есть новый вызов BeginSampleScan
должен привести к выбору тех же кортежей, что и раньше (если параметры TABLESAMPLE
и seed
не меняются).
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) в том случае, если таких ресурсов нет.