Documentação do PostgreSQL 8.0.0 | ||||
---|---|---|---|---|
Anterior | Início | Capítulo 41. Visão geral da estrutura interna do PostgreSQL | Fim | Próxima |
O executor recebe o plano retornado pelo planejador/otimizador, e o processa recursivamente para extrair o conjunto de linhas requisitadas. É essencialmente um mecanismo de canal de envio de informação sob demanda. Toda vez que o nodo do plano é chamado deve enviar mais uma linha, ou relatar que não há mais linha a ser enviada.
Para fornecer um exemplo concreto, será assumido que o nodo do topo é um nodo MergeJoin (junção por mesclagem). Antes da mesclagem poder ser feita, devem ser trazidas duas linhas (uma de cada subplano). Assim, o executor chama a si próprio recursivamente para processar os subplanos (começa pelo subplano anexado à lefttree — árvore da esquerda). Digamos que o novo nodo do topo (o nodo do topo do subplano da esquerda) seja um nodo Sort (classificação), e novamente haja necessidade de recursão para obter a linha de entrada. O nodo filho do Sort deve ser um nodo SeqScan, representando a leitura real da tabela. A execução deste nodo faz o executor trazer uma linha da tabela e retorná-la para o nodo que chamou. O nodo Sort chama repetitivamente seu nodo filho para obter todas as linhas a serem classificadas. Quando a entrada é exaurida (conforme indicado pelo nodo filho retornando nulo em vez de uma linha), o código do Sort realiza a classificação, e finalmente é capaz de retornar sua primeira linha de saída, que é a primeira linha na ordem da classificação. As demais linhas são mantidas armazenadas, para que possa enviá-las na ordem da classificação em resposta aos próximos comandos.
De maneira semelhante, o nodo MergeJoin solicita a primeira linha de seu subplano da direita. Depois compara as duas linhas para verificar se podem ser juntadas; se puderem ser juntadas, retorna a linha juntada para quem chamou. Na próxima chamada, ou imediatamente se não puder juntar as duas entradas, avança para a próxima linha de uma tabela ou da outra (dependendo do que ocorrer na comparação), e novamente compara. No final, um dos dois subplanos ficará exaurido, e o nodo de MergeJoin retorna nulo para indicar que não podem ser formadas mais linhas pela junção.
Os comandos complexos podem envolver muitos níveis de nodos de plano, mas a abordagem geral é a mesma: cada nodo computa e retorna sua próxima linha de saída cada vez que é chamado. Cada nodo é responsável pela aplicação da seleção e das expressões de projeção atribuídas ao mesmo pelo planejador.
O mecanismo do executor é utilizado para avaliar todos os quatro tipos de comando SQL básicos: SELECT, INSERT, UPDATE e DELETE. Para o SELECT, o código de nível mais alto do executor somente precisa enviar para o cliente cada linha retornada pelo plano de comando. Para o INSERT, cada linha retornada é inserida na tabela de destino especificada para o INSERT (Um comando INSERT ... VALUES cria uma árvore de plano trivial, consistindo de um único nodo Result que computa apenas uma linha de resultado, mas o comando INSERT ... SELECT pode demandar todo o poder do mecanismo do executor). Para o UPDATE, o planejador faz com que cada linha computada inclua os valores de todas as colunas atualizadas, mais o TID (ID da tupla, ou ID da linha) da linha de destino original; o nível superior do executor utiliza esta informação para criar uma nova linha atualizada, e marcar a linha antiga como excluída. Para o DELETE, a única coluna realmente retornada pelo plano é a TID, e o nível superior do executor simplesmente utiliza o TID para visitar cada linha de destino e marcá-la como excluída.