Lidando com o erro “Query processor could not produce a query plan”

Atendendo a uma demanda de cliente, onde no cenário precisamos realizar uma sumarização de dados das últimas operações de clientes consolidando tudo dentro de um determinado período.

Ocorria que a consulta iria percorrer a maior tabela do cliente, a tabela chega a representar mais de 80% do tamanho do banco de dados do cliente, portanto era muito importante que nossa consulta, trabalhasse de maneira obrigatória com um índice filtrado, pois nossa consulta desejava apenas um range de informação da tabela, e foi criado um índice apenas para aquele período, para justamente não corrermos o risco de um plano de execução mau elaborado realizasse um fullscan no database fazendo com que não apenas a consulta demorasse muito como também iria comprometer todo o hardware de produção do cliente.

Neste exemplo, a big table é a tabela  Vendas (exemplo hipotético)

Após montar um script (exemplo hipotético simples), abaixo, o sql server resultou em erro:

declare @data_venda datetime = '2017-05-01';

with clientes as (
       select cod_cliente from clientes
       where 
       ultima_acao > @data_venda
       )
,ultima_venda_cliente  as (select  distinct v.cod_cliente, max(v.data_venda) over( partition by v.cod_cliente order by v.data_venda desc)
              from vendas v with(nolock, index(idx_filtrado_vendas_cliente_data))
              join clientes vp  on vp.cod_cliente = c.cod_cliente
              where
              v.data_venda >= @data_venda
              )
select * from ultima_venda_cliente



Msg 8622, Level 16, State 1, Line 6
Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using SET FORCEPLAN.

Para quem não é persistente, acreditaria pela mensagem de erro que não é possível forcar nesta consulta a utilização de um índice filtrado, pois a mensagem de erro manda submeter a consulta novamente sem hint e afirmando que a utilização do hint é a casa do problema.

A solução é tão simples que quando realizei, quase não acreditei, e foi puramente por acaso que descobri, porque em uma rápida pesquisa na net nada encontrei documentado a respeito.

Basta não trabalhar com parâmetros dentro da CTE onde forço a utilização do índices e está tudo resolvido.

declare @data_venda datetime = '2017-05-01';

with clientes as (
       select cod_cliente from clientes
       where 
       ultima_acao > @data_venda
       )
,ultima_venda_cliente  as (select  distinct v.cod_cliente, max(v.data_venda) over( partition by v.cod_cliente order by v.data_venda desc)
              from vendas v with(nolock, index(idx_filtrado_vendas_cliente_data))
              join clientes vp  on vp.cod_cliente = c.cod_cliente
              where
              v.data_venda >=  '2017-05-01'-- aqui não pode ter parametros @data_venda
              )
select * from ultima_venda_cliente

 

Translate »