Um Ministério Público Estadual tem posse de uma base de dados intitulada processos, criada no PostgreSQL 11+, em condições ideais, majoritariamente append-only nas quais são utilizados planos do tipo index-only scan. Contudo, ainda apresenta muitos heap fetches quando comandos são executados com EXPLAIN (ANALYZE, BUFFERS). A ação operacional que tende a viabilizar a leitura somente pelo índice com maior consistência é
Aalterar o nível de isolamento para REPEATABLE READ na sessão de leitura, pois isso torna as tuplas implicitamente visíveis ao índice.
Bforçar enable_seqscan = off na sessão, pois isso converte o plano em index-only scan evitando leituras no heap.
Cajustar random_page_cost para reduzir a penalidade de acesso aleatório e induzir o otimizador a evitar o heap.
Dexecutar VACUUM (rotineiro/automático bem ajustado) para aumentar a marcação all-visible e reduzir a necessidade de visitar o heap.
Ecriar um índice B-tree comINCLUDE nas colunas projetadas, pois isso elimina a dependência de visibilidade de tuplas no heap.
Revelar gabarito e comentário▾
GabaritoD — executar VACUUM (rotineiro/automático bem ajustado) para aumentar a marcação all-visible e reduzir a necessidade de visitar o heap.
Comentário gerado por IA. É um apoio ao estudo, ancorado em fontes, mas pode conter imprecisões — confira sempre na fonte oficial (lei, súmula, edital e gabarito da banca). Encontrou um erro? Use “Reportar”.
Index-only scan no PostgreSQL: o papel do VACUUM e da visibilidade das tuplas
Gabarito: letra D. O index-only scan no PostgreSQL só consegue ler exclusivamente pelo índice quando o heap não precisa ser consultado para verificar a visibilidade das tuplas — e essa verificação é dispensada quando a página do heap está marcada como all-visible, marcação que é feita pelo VACUUM. Portanto, a ação operacional que tende a viabilizar a leitura somente pelo índice com maior consistência é executar VACUUM (rotineiro/automático bem ajustado) para aumentar a marcação all-visible e reduzir a necessidade de visitar o heap.
O index-only scan é uma técnica de otimização de consultas em que o PostgreSQL tenta responder a uma consulta lendo apenas as entradas do índice, sem precisar acessar a tabela (o heap). Isso é possível quando todas as colunas necessárias para a consulta estão presentes no índice. No entanto, há um detalhe crucial: o PostgreSQL precisa saber se a tupla é visível para a transação atual, e essa informação de visibilidade (devido ao controle de concorrência multiversão — MVCC) está armazenada no heap, não no índice. Para evitar a visita ao heap, o PostgreSQL usa o mapa de visibilidade (visibility map), que registra quais páginas do heap contêm apenas tuplas visíveis para todas as transações. Quando uma página está marcada como all-visible, o PostgreSQL confia nessa marcação e não precisa ir ao heap para verificar a visibilidade de cada tupla.
O VACUUM é a ferramenta que mantém o mapa de visibilidade atualizado. Ele remove tuplas mortas (versões antigas de linhas que não são mais visíveis para nenhuma transação) e, ao fazer isso, marca as páginas que ficaram com apenas tuplas visíveis como all-visible. Em uma tabela append-only (onde os dados são apenas inseridos, nunca atualizados ou excluídos), as tuplas nunca se tornam mortas, mas as páginas recém-inseridas podem não estar marcadas como all-visible até que o VACUUM as examine. Portanto, um VACUUM bem ajustado (ou o autovacuum) é essencial para que o index-only scan funcione de forma consistente, reduzindo os heap fetches.
Vamos entender por que as outras alternativas não resolvem o problema:
A) Alterar o nível de isolamento para REPEATABLE READ: O nível de isolamento controla quais fenômenos de concorrência podem ocorrer (leitura suja, leitura não repetível, leitura fantasma). Ele não tem relação com a visibilidade das tuplas no heap para o index-only scan. O MVCC do PostgreSQL usa o número da transação (XID) para determinar a visibilidade, e isso é independente do nível de isolamento. Mudar o isolamento não faz as tuplas ficarem "implicitamente visíveis ao índice".
B) Forçar enable_seqscan = off: Essa configuração desencoraja o planejador de usar sequential scans, mas não força o uso de index-only scan. O planejador pode escolher um index scan comum (que ainda acessa o heap para buscar a linha) ou outro método. Além disso, desligar o seqscan é uma medida drástica que pode piorar o desempenho geral, e não resolve a questão da visibilidade das tuplas.
C) Ajustar random_page_cost: Esse parâmetro influencia a estimativa de custo do planejador para acessos aleatórios (como os feitos por índices). Reduzi-lo pode tornar os planos com índice mais atraentes, mas não garante que o index-only scan seja usado, nem resolve o problema dos heap fetches causados pela falta de marcação all-visible.
E) Criar um índice B-tree com INCLUDE nas colunas projetadas: Um índice com INCLUDE adiciona colunas ao índice que não são usadas para busca, mas que podem ser retornadas diretamente pelo índice. Isso ajuda a evitar a visita ao heap para buscar essas colunas, mas não elimina a dependência de visibilidade. O PostgreSQL ainda precisa verificar se a tupla é visível, e essa verificação pode exigir o acesso ao heap, a menos que a página esteja marcada como all-visible. Portanto, o INCLUDE sozinho não resolve o problema dos heap fetches.
A pegadinha desta questão está em confundir as técnicas de otimização de consultas. O candidato pode pensar que criar um índice com INCLUDE ou ajustar parâmetros do otimizador resolve o problema, mas a causa raiz dos heap fetches em um index-only scan é a falta de marcação all-visible nas páginas do heap, que só o VACUUM pode resolver.
1Consulta usa índice
2Precisa checar visibilidade
3Heap tem a informação
4Página all-visible?
5Sim → lê só índice
6Não → heap fetch
LEVEL · soulevel.com.br
Alternativa A — ❌ Incorreta
O nível de isolamento REPEATABLE READ controla a consistência de leitura dentro de uma transação, evitando leituras não repetíveis e fantasmas. Ele não tem nenhum efeito sobre a visibilidade das tuplas no heap para o index-only scan. A visibilidade é determinada pelo MVCC, que compara o XID da tupla com o XID da transação atual, independentemente do nível de isolamento. Portanto, essa alternativa não reduz os heap fetches.
Alternativa B — ❌ Incorreta
Desligar o enable_seqscan apenas desencoraja o planejador de usar sequential scans. Ele pode escolher um index scan comum (que acessa o heap para buscar a linha) ou até mesmo um bitmap heap scan. Não há garantia de que o plano se torne um index-only scan, e mesmo que se torne, o problema da visibilidade das tuplas permanece. Essa é uma medida paliativa e não resolve a causa raiz.
Alternativa C — ❌ Incorreta
O random_page_cost é um parâmetro de custo que influencia a escolha do planejador entre acessos sequenciais e aleatórios. Reduzi-lo pode tornar os planos com índice mais atraentes, mas não garante o uso de index-only scan nem resolve a necessidade de verificar a visibilidade no heap. O otimizador pode escolher um index scan comum, que ainda faz heap fetches.
Alternativa D — ✅ Correta ⟵ GABARITO
O VACUUM é a operação que atualiza o mapa de visibilidade, marcando as páginas do heap que contêm apenas tuplas visíveis para todas as transações como all-visible. Quando uma página está marcada como all-visible, o PostgreSQL pode usar o index-only scan sem precisar acessar o heap para verificar a visibilidade de cada tupla. Em uma tabela append-only, o VACUUM (ou o autovacuum bem ajustado) é essencial para manter essa marcação atualizada, reduzindo os heap fetches e viabilizando a leitura somente pelo índice com maior consistência.
Alternativa E — ❌ Incorreta
Um índice com INCLUDE adiciona colunas ao índice que podem ser retornadas diretamente, evitando a visita ao heap para buscar essas colunas. No entanto, isso não elimina a dependência de visibilidade. O PostgreSQL ainda precisa verificar se a tupla é visível para a transação atual, e essa verificação pode exigir o acesso ao heap, a menos que a página esteja marcada como all-visible. Portanto, o INCLUDE sozinho não resolve o problema dos heap fetches.