Перейти к основному содержимому

Вспомогательные функции метода выборки

Функция-обработчик 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) в том случае, если таких ресурсов нет.