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