57.1. Функции поддержки метода выборки#

57.1. Функции поддержки метода выборки

57.1. Функции поддержки метода выборки #

Функция обработчика 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() для попытки сократить эти выражения до констант, если их значения необходимы для оценки; но функция должна предоставлять оценки размера даже если они не могут быть сокращены, и она не должна завершаться с ошибкой, даже если значения кажутся недопустимыми (помните, что они являются только оценками того, какими будут значения во время выполнения). Параметры 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) истинно, сканирование фактически не будет выполнено, поэтому эта функция должна выполнять только минимально необходимые действия, чтобы сделать состояние узла допустимым для 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 и начальное значение не изменяются).

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