Pular para o conteúdo principal

Questão de Banco de Dados — Otimização (Tuning) em Banco de Dados — FCC 2026

Banco de DadosOtimização (Tuning) em Banco de Dados
Código
fc142242
Banca
FCC
Órgão
MPE AP
Ano
2026
Cargo
Ana Min ( )
Um técnico de um Ministério Público é responsável por analisar movimentações financeiras armazenadas na tabela transacoes de um banco de dados MySQL, que já conta com milhões de registros: CREATE TABLE transacoes (   id BIGINT AUTO_INCREMENT PRIMARY KEY,   cliente_id INT,   valor DECIMAL(10,2),   data DATE ); Ele precisa gerar um relatório para apurar o valor total movimentado por cada cliente no ano de 2025. Sua primeira tentativa foi por meio do comando abaixo: SELECT cliente_id, SUM(valor) FROM transacoes WHERE YEAR(data) = 2025 GROUP BY cliente_id; Entretanto, a consulta se mostrou lenta e impactando o desempenho do banco de dados. Nesse caso, a alteração mais indicada para otimizar essa execução é
  1. Acriar um índice em YEAR(data) para acelerar o filtro e agrupar por cliente_id e data.
  2. Bsubstituir WHERE YEAR(data) = 2025 por WHERE data BETWEEN '2025-01-01' AND '2025-12-31'.
  3. Cconverter a coluna data para texto (VARCHAR) e filtrar com LIKE '2025%'.
  4. Dreescrever a consulta com DISTINCT cliente_id antes de somar os valores.
  5. Eforçar o MySQL a usar FORCE INDEX (cliente_id) mesmo que o filtro seja pela data.
Revelar gabarito e comentário

GabaritoB — substituir WHERE YEAR(data) = 2025 por WHERE data BETWEEN '2025-01-01' AND '2025-12-31'.

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: filtro por função vs. intervalo

Gabarito: letra B. A lentidão da consulta decorre do uso de WHERE YEAR(data) = 2025, que aplica uma função sobre a coluna data e impede o uso de um índice nessa coluna, forçando uma varredura completa da tabela (full table scan). A otimização mais indicada é substituir essa condição por um filtro de intervalo com BETWEEN, que permite ao MySQL usar um índice na coluna data para localizar diretamente as linhas do ano de 2025.

O problema central aqui é a sargabilidade (do inglês Search ARGument ABLE) de uma condição. Uma condição é sargável quando o SGBD consegue usar um índice para resolvê-la. Quando você escreve YEAR(data) = 2025, está aplicando uma função na coluna data. Isso faz com que o MySQL precise calcular o ano de cada valor da coluna para depois comparar com 2025 — ou seja, ele não pode simplesmente pular para o trecho do índice que contém os valores de 2025. O resultado é uma varredura completa da tabela, lendo todos os milhões de registros para avaliar a condição.

A solução clássica é reescrever a condição para que a coluna fique sozinha de um lado da comparação, permitindo que o otimizador use um índice. No caso de datas, isso significa transformar YEAR(data) = 2025 em um intervalo: data BETWEEN '2025-01-01' AND '2025-12-31'. Agora a coluna data não está envolvida em nenhuma função, e o MySQL pode usar um índice (se existir) para encontrar rapidamente todas as linhas dentro desse intervalo. Essa é a técnica mais direta e eficaz para este cenário.

Vamos entender por que as outras alternativas não resolvem o problema ou até o pioram. Criar um índice em YEAR(data) (alternativa A) não é possível na maioria dos SGBDs, pois índices são criados sobre colunas, não sobre expressões (a menos que sejam functional indexes, que não é o caso padrão do MySQL). Converter a coluna para texto e usar LIKE '2025%' (alternativa C) também impede o uso de índice e ainda adiciona overhead de conversão. Usar DISTINCT (alternativa D) não tem relação com o filtro por data e não acelera a agregação. Forçar o uso de um índice em cliente_id (alternativa E) é contraproducente, pois o filtro é pela data, não pelo cliente.

A pegadinha desta questão é que o candidato pode se confundir e achar que a solução é criar um índice na coluna data ou usar FORCE INDEX. Mas a questão não pergunta qual índice criar — ela pergunta qual alteração na consulta é mais indicada. E a resposta é reescrever o filtro para torná-lo sargável. Guarde essa distinção: otimizar a consulta (reescrever o SQL) é diferente de otimizar o esquema (criar índices). Aqui, a banca quer que você identifique o problema na escrita do SQL e aplique a correção mais simples e eficaz.

Condição sargável
  • 1Coluna sozinha na comparação
    • Usa índice
    • Ex.: data BETWEEN '2025-01-01' AND '2025-12-31'
  • 2Função na coluna
    • Impede índice
    • Ex.: YEAR(data) = 2025
    • Full table scan
LEVEL · soulevel.com.br

Alternativa A — ❌ Incorreta

Criar um índice em YEAR(data) não é uma prática comum no MySQL (que não suporta índices funcionais nativamente até versões recentes) e, mesmo que fosse possível, o índice seria sobre uma expressão, não sobre a coluna. Além disso, agrupar por cliente_id e data mudaria o resultado da consulta, pois o GROUP BY original agrupa apenas por cliente_id. A alternativa mistura duas ideias erradas: índice em função e agrupamento incorreto.

Alternativa B — ✅ Correta ⟵ GABARITO

Substituir WHERE YEAR(data) = 2025 por WHERE data BETWEEN '2025-01-01' AND '2025-12-31' torna a condição sargável. A coluna data fica livre de funções, permitindo que o MySQL use um índice nessa coluna (se existir) para acessar diretamente as linhas do período. Isso reduz drasticamente o número de registros lidos, acelerando a consulta. É a técnica padrão de otimização para filtros por período em colunas de data.

Alternativa C — ❌ Incorreta

Converter a coluna data para VARCHAR e usar LIKE '2025%' é uma péssima prática. Além de exigir uma conversão de tipo em cada linha (o que impede o uso de índice), a comparação com LIKE em uma coluna de texto não é sargável quando o padrão começa com curinga, e mesmo começando com um prefixo fixo, a conversão da coluna anula qualquer possibilidade de uso de índice. O resultado seria uma consulta ainda mais lenta.

Alternativa D — ❌ Incorreta

Usar DISTINCT cliente_id antes de somar os valores não faz sentido lógico. A consulta original já agrupa por cliente_id com GROUP BY, e o SUM(valor) é calculado para cada grupo. Adicionar DISTINCT não altera o plano de execução de forma a melhorar o desempenho; na verdade, pode até adicionar uma etapa extra de ordenação/remoção de duplicatas, tornando a consulta mais lenta. O problema da consulta original é o filtro por YEAR(data), não a agregação.

Alternativa E — ❌ Incorreta

Forçar o uso de um índice em cliente_id com FORCE INDEX é contraproducente. O filtro da consulta é pela coluna data, não por cliente_id. Usar um índice em cliente_id não ajuda a localizar as linhas do ano de 2025; pelo contrário, o MySQL seria forçado a percorrer o índice de cliente_id e depois acessar a tabela para verificar a condição de data, o que pode ser até mais lento que uma varredura completa. A diretriz correta seria criar um índice em data (ou um índice composto em data, cliente_id), mas a questão pede uma alteração na consulta, não no esquema.

Gabarito: letra B

Link permanente: /questoes/fc142242