Questão de Banco de Dados — Otimização (Tuning) em Banco de Dados — FCC 2026
Banco de Dados›Otimização (Tuning) em Banco de Dados
Código
fc142369
Banca
FCC
Órgão
MPE SE
Ano
2026
Cargo
Ana ( )
Um analista precisa otimizar o desempenho da consulta SQL abaixo, que é crítica para o acompanhamento de processos, mas que está apresentando alto custo de execução devido ao volume superior a 10 milhões de registros na tabela Investigacao:
SELECT p.nome, COUNT(i.id_investigacao) AS total_investigacoes FROM Promotor p INNER JOIN Investigacao i ON p.id_promotor = i.fk_promotor WHERE i.data_abertura >= '2025-01-01' GROUP BY p.nome ORDER BY total_investigacoes DESC;
Considerando a necessidade de otimizar, em uma única estrutura de índice na tabela Investigacao, as operações de JOIN (fk_promotor), FILTER (data_abertura) e AGGREGATION (COUNT), a ação de indexação mais completa e tecnicamente adequada para possibilitar um index-only scan (consulta baseada em índice de cobertura) e minimizar o acesso à tabela principal é:
ACREATE INDEX idx_investigacao_id ON Investigacao (id_investigacao);
BCREATE INDEX idx_investigacao_fk_data_id ON Investigacao (fk_promotor, data_abertura, id_investigacao);
CCREATE INDEX idx_investigacao_data ON Investigacao (data_abertura);
DCREATE INDEX idx_investigacao_fk ON Investigacao (fk_promotor);
ECREATE INDEX idx_investigacao_fk_data ON Investigacao (fk_promotor, data_abertura);
Revelar gabarito e comentário▾
GabaritoB — CREATE INDEX idx_investigacao_fk_data_id ON Investigacao (fk_promotor, data_abertura, id_investigacao);
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”.
Otimização de consultas SQL: índice de cobertura (covering index)
Gabarito: letra B. Para possibilitar um index-only scan (varredura apenas pelo índice, sem acesso à tabela), o índice composto deve conter todas as colunas referenciadas na consulta: a coluna de junção (fk_promotor), a coluna de filtro (data_abertura) e a coluna de agregação (id_investigacao). O índice (fk_promotor, data_abertura, id_investigacao) cobre exatamente essas três necessidades, permitindo que o SGBD responda à consulta inteiramente pelo índice, minimizando o I/O.
O conceito central aqui é o índice de cobertura (covering index). Um índice é dito "coberto" quando contém todas as colunas necessárias para resolver uma consulta, de modo que o SGBD não precise buscar os dados na tabela principal (heap). Isso reduz drasticamente o custo de execução, especialmente em tabelas com milhões de registros, como a Investigacao com mais de 10 milhões de linhas.
Para entender por que a alternativa B é a correta, é preciso decompor a consulta em suas operações:
JOIN: a junção entre Promotor e Investigacao é feita pela condição p.id_promotor = i.fk_promotor. Para acelerar essa operação, é fundamental ter um índice na coluna fk_promotor da tabela Investigacao.
FILTER: a cláusula WHERE filtra as linhas por data_abertura >= '2025-01-01'. Um índice que inclua data_abertura permite que o SGBD localize rapidamente apenas as linhas que atendem ao filtro, sem varrer a tabela inteira.
AGGREGATION: a função COUNT(i.id_investigacao) precisa contar os registros por grupo. Se o índice incluir id_investigacao, o SGBD pode contar diretamente as entradas do índice, sem acessar a tabela.
A ordem das colunas no índice composto também é relevante. A regra prática é colocar primeiro as colunas usadas em condições de igualdade (JOIN), depois as colunas de filtro por faixa (WHERE com >=), e por fim as colunas de projeção/agregação. Isso porque o índice é organizado de forma que as colunas iniciais determinam a ordenação, permitindo buscas eficientes por igualdade e, em seguida, por faixa.
Um exemplo prático: imagine que a tabela Investigacao tenha 10 milhões de linhas. Sem índice, o SGBD precisaria ler todas as 10 milhões de linhas para aplicar o filtro de data e fazer a junção. Com o índice (fk_promotor, data_abertura, id_investigacao), o SGBD pode percorrer apenas as entradas do índice que correspondem aos promotores e às datas relevantes, contando os id_investigacao diretamente. O acesso à tabela principal é eliminado, reduzindo o I/O de milhões de leituras para algumas centenas ou milhares.
A pegadinha desta questão está em reconhecer que o índice precisa ser composto e cobrir todas as colunas. Alternativas que criam índices em apenas uma coluna (A, C, D) ou em duas colunas (E) não são suficientes para um index-only scan, pois o SGBD ainda precisaria acessar a tabela para obter a coluna que falta. A alternativa B é a única que inclui as três colunas necessárias.
Guarde este critério: para um covering index, o índice deve conter todas as colunas da consulta (SELECT, WHERE, JOIN, GROUP BY, ORDER BY). É exatamente essa completude que separa a alternativa correta das demais.
Alternativa
Índice proposto
Cobre JOIN (fk_promotor)
Cobre FILTER (data_abertura)
Cobre COUNT (id_investigacao)
Permite index-only scan?
A
(id_investigacao)
❌
❌
✅
❌
B
(fk_promotor, data_abertura, id_investigacao)
✅
✅
✅
✅
C
(data_abertura)
❌
✅
❌
❌
D
(fk_promotor)
✅
❌
❌
❌
E
(fk_promotor, data_abertura)
✅
✅
❌
❌
Índice de cobertura (covering index): Requisito (Todas as colunas da consulta, SELECT, WHERE, JOIN, GROUP BY); Ordem das colunas (Igualdade (JOIN), Faixa (WHERE), Projeção/agregação (COUNT)); Benefício (Index-only scan, Sem acesso à tabela (heap))
Alternativa A — ❌ Incorreta
Cria um índice apenas na coluna id_investigacao. Essa coluna é usada apenas na função COUNT, mas o índice não cobre a coluna de junção fk_promotor nem a de filtro data_abertura. O SGBD ainda precisaria acessar a tabela para aplicar o filtro e fazer a junção, impossibilitando um index-only scan.
Alternativa B — ✅ Correta ⟵ GABARITO
Cria um índice composto com as três colunas necessárias: fk_promotor (JOIN), data_abertura (FILTER) e id_investigacao (COUNT). Com esse índice, o SGBD pode resolver a consulta inteiramente pelo índice, sem acessar a tabela principal. A ordem das colunas também é adequada: primeiro a coluna de igualdade (JOIN), depois a de faixa (WHERE), e por fim a de agregação.
Alternativa C — ❌ Incorreta
Cria um índice apenas na coluna data_abertura. Embora acelere o filtro por data, não cobre a coluna de junção fk_promotor nem a de agregação id_investigacao. O SGBD precisaria acessar a tabela para obter essas colunas, inviabilizando o index-only scan.
Alternativa D — ❌ Incorreta
Cria um índice apenas na coluna fk_promotor. Acelera a junção, mas não cobre o filtro por data_abertura nem a agregação por id_investigacao. O acesso à tabela principal ainda seria necessário, impedindo o index-only scan.
Alternativa E — ❌ Incorreta
Cria um índice composto com fk_promotor e data_abertura, cobrindo JOIN e FILTER. No entanto, falta a coluna id_investigacao, usada na função COUNT. O SGBD precisaria acessar a tabela para contar os registros, o que impede o index-only scan completo.
PEGA ESSA DICA!
Para identificar um covering index em questões de otimização, liste todas as colunas que aparecem na consulta (SELECT, WHERE, JOIN, GROUP BY, ORDER BY) e verifique se o índice proposto contém todas elas. Se faltar qualquer uma, o índice não é de cobertura.