59.1. Funções de suporte ao método de amostragem #

A função do tratador de TSM retorna uma estrutura TsmRoutine alocada usando palloc contendo ponteiros para as funções de suporte descritas abaixo. A maioria das funções são obrigatórias, mas algumas são opcionais, e estes ponteiros podem ser NULL.

void
SampleScanGetSampleSize (PlannerInfo *root,
                         RelOptInfo *baserel,
                         List *paramexprs,
                         BlockNumber *pages,
                         double *tuples);

Esta função é chamada durante o planejamento. Deve estimar o número de páginas da relação que serão lidas durante uma varredura de amostra e o número de tuplas que serão selecionadas pela varredura. (Por exemplo, podem ser determinados estimando a fração da amostragem e, em seguida, multiplicando os números baserel->pages e baserel->tuples por esta fração, certificando-se de arredondar os resultados para valores inteiros.) A lista paramexprs contém a(s) expressão(ões) que são parâmetros para a cláusula TABLESAMPLE. É recomendável usar estimate_expression_value() para tentar reduzir estas expressões a constantes, se seus valores forem necessários para fins de estimativa; mas a função deve fornecer estimativas de tamanho mesmo que elas não possam ser reduzidas, e não deve falhar mesmo que os valores pareçam inválidos (lembre-se de que são apenas estimativas de quais serão os valores de tempo de execução). Os parâmetros pages and tuples são de saída.

void
InitSampleScan (SampleScanState *node,
                int eflags);

Inicializa para execução de um nó de plano SampleScan. É chamada durante a ativação do executor. Deve executar qualquer inicialização necessária antes que o processamento possa começar. O nó SampleScanState já foi criado, mas seu campo tsm_state é NULL. A função InitSampleScan pode armazenar quaisquer dados de estado interno necessários ao método de amostragem e armazenar um ponteiro para eles em node->tsm_state. As informações sobre a tabela a ser varrida são acessíveis por meio de outros campos do nó SampleScanState (mas note que o descritor de varredura node->ss.ss_currentScanDesc ainda não está configurado). eflags contém bits sinalizadores que descrevem o modo de operação do executor para este nó de plano.

Quando (eflags & EXEC_FLAG_EXPLAIN_ONLY) for verdade, a varredura não será realmente executada, então esta função deve fazer apenas o mínimo necessário para tornar o estado do nó válido para EXPLAIN e EndSampleScan.

Esta função pode ser omitida (definindo o ponteiro como NULL), e neste caso BeginSampleScan deve executar toda a inicialização necessária pelo método de amostragem.

void
BeginSampleScan (SampleScanState *node,
                 Datum *params,
                 int nparams,
                 uint32 seed);

Inicia a execução de uma varredura de amostragem. É chamada logo antes da primeira tentativa de buscar uma tupla, podendo ser chamada novamente se a varredura precisar ser reiniciada. As informações sobre a tabela a ser varrida são acessíveis por meio dos campos do nó SampleScanState (mas note que o descritor de varredura node->ss.ss_currentScanDesc ainda não está configurado). A matriz params, de comprimento nparams, contém os valores dos parâmetros fornecidos na cláusula TABLESAMPLE. Terão o número e os tipos especificados na lista parameterTypes do método de amostragem, e foram verificados para não serem nulos. seed contém a semente para ser usada em quaisquer números aleatórios gerados dentro do método de amostragem; é um hash derivado do valor REPEATABLE se um foi fornecido, ou o resultado de random() se não foi.

Esta função pode ajustar os campos node->use_bulkread e node->use_pagemode. Se node->use_bulkread for true, que é o padrão, a varredura usará uma estratégia de acesso ao buffer que incentiva a reciclagem dos buffers após o uso. Pode ser razoável definir como false se a varredura visitar apenas uma pequena fração das páginas da tabela. Se node->use_pagemode for true, que é o padrão, a varredura executará a verificação de visibilidade em uma única passagem para todas as tuplas em cada página visitada. Pode ser razoável definir como false se a varredura selecionar apenas uma pequena fração das tuplas em cada página visitada. Isto resultará em menos verificações de visibilidade de tuplas sendo realizadas, embora cada uma delas seja mais cara porque exigirá mais bloqueios.

Se o método de amostragem estiver marcado com repeatable_across_scans, deve ser capaz de selecionar o mesmo conjunto de tuplas durante uma nova varredura como fez originalmente, ou seja, uma nova chamada de BeginSampleScan deve levar à seleção das mesmas tuplas de antes (se os parâmetros TABLESAMPLE e a semente não mudarem).

BlockNumber
NextSampleBlock (SampleScanState *node, BlockNumber nblocks);

Retorna o número do bloco da próxima página a ser varrida, ou InvalidBlockNumber se não houver mais páginas para serem varridas.

Esta função pode ser omitida (definindo o ponteiro como NULL), caso em que o código núcleo executará uma varredura sequencial de toda a relação. Esta varredura pode usar a varredura sincronizada, de modo que o método de amostragem não pode presumir que as páginas de relação são visitadas na mesma ordem em cada varredura.

OffsetNumber
NextSampleTuple (SampleScanState *node,
                 BlockNumber blockno,
                 OffsetNumber maxoffset);

Retorna o número do deslocamento da próxima tupla a ser amostrada na página especificada, ou InvalidOffsetNumber se não houver mais tuplas para serem amostradas. maxoffset é o maior número de deslocamento em uso na página.

Nota

NextSampleTuple não é explicitamente informada sobre quais dos números de deslocamento no intervalo 1 .. maxoffset realmente contém tuplas válidas. Isto normalmente não é um problema, porque o código núcleo ignora solicitações para amostrar tuplas ausentes ou invisíveis; não deve resultar em nenhuma distorção na amostra. Entretanto, se necessário, a função pode usar node->donetuples para examinar quantas das tuplas retornadas eram válidas e visíveis.

Nota

NextSampleTuple não deve assumir que blockno é o mesmo número de página retornado pela chamada NextSampleBlock mais recente. Este foi retornado por alguma chamada anterior a NextSampleBlock, mas o código núcleo tem permissão para chamar NextSampleBlock antes de varrer realmente as páginas, para dar suporte à pré-busca. É aceitável assumir que, uma vez iniciada a amostragem de uma determinada página, as chamadas sucessivas a NextSampleTuple referem-se todas à mesma página até que InvalidOffsetNumber seja retornado.

void
EndSampleScan (SampleScanState *node);

Encerra a varredura e libera os recursos. Normalmente não é importante liberar memória alocada usando palloc, mas quaisquer recursos visíveis externamente devem ser limpos. Esta função pode ser omitida (definindo o ponteiro como NULL) no caso comum em que estes recursos não existam.