AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 290245
Accepted
Simon_Weaver
Simon_Weaver
Asked: 2021-04-22 19:40:12 +0800 CST2021-04-22 19:40:12 +0800 CST 2021-04-22 19:40:12 +0800 CST

O índice de data SEEK é escolhido ao usar OPTION RECOMPILE, mas não com OPTION OPTIMIZE FOR

  • 772

Eu tenho uma tabela contendo 10 anos de 'varreduras de pacotes'. Alguém verifica um pacote e registra a data e o nome de usuário. Vamos fingir por enquanto que reter 10 anos de dados realmente tem um propósito.

Eu tenho uma página para mostrar um resumo da semana passada, então claramente quero ler apenas 1 semana de dados.

Aqui está a consulta, a ser executada no SSMS duas vezes, uma com uma data recente codificada e novamente com uma data antiga em 2013 . É originalmente uma consulta parametrizada, mas no SSMS estou substituindo @p0pela data:

SELECT [t0].[VerifyDate], [t0].[PackageId], [t0].[Username]
FROM [dbo].[PackageVerification] AS [t0]
INNER JOIN [dbo].[Package] AS [t1] ON [t1].[PackageId] = [t0].[PackageId]

WHERE ([t1].[PackageStatus] <> 99) AND ([t0].[VerifyDate] > @p0)   
ORDER BY [t0].[VerifyDate] DESC

Antes de executá-lo, gostaria de apresentar meu índice de datas.

Agora, meu índice de data não está na minha PackageVerificationtabela, mas em uma 'visualização auxiliar' que executa a mesma junção vista acima. A consulta acima é capaz de usar magicamente essa exibição indexada porque tenho SCHEMABINDING ativado.

CREATE NONCLUSTERED INDEX [IX_Helper_PackageVerification_USER_SCAN_HISTORY] ON [dbo].[Helper_PackageVerification]
(
    [VerifyDate] DESC,
    [PackageStatus] ASC
)
INCLUDE (
    [VerifyDateDate],
    [Username]
) 

Quando executo a consulta no SSMS com uma data antiga e nova, ele usa a varredura ou busca conforme o esperado. O limite parece estar em algum lugar por volta de 2015. Portanto, qualquer coisa remotamente recente deve definitivamente estar usando uma busca. Aqui estão os resultados disso:

insira a descrição da imagem aqui

Quando executo como uma consulta parametrizada do meu aplicativo , sempre recebo uma varredura completa , que por algum motivo usa um plano paralelizado.

Pelo menos está usando meu índice auxiliar.

insira a descrição da imagem aqui

Na verdade, não sei por que não recebo sniffing de parâmetros para isso. Eu sempre passo uma data muito recente, então eu teria pensado que poderia ter preferido uma varredura, mas estou bem com isso escolhendo o plano acima, dadas as circunstâncias. Há mais de um milhão de linhas e leva cerca de 150 ms.

Aliás, este é um banco de dados SQL Azure com 2vCores. A detecção de parâmetros é habilitada e a parametrização é definida como simples .

Se eu alterar a consulta e executar meu aplicativo usando ,OPTION (RECOMPILE) recebo o SEEK desejado e um desempenho muito bom de apenas alguns ms. O tempo de recompilação parece ser insignificante e, francamente, este é um desempenho perfeitamente bom que posso usar.

Quando procuro na loja de consultas, posso verificar que a OPÇÃO RECOMPILE usa a busca por uma data recente e a varredura de uma data antiga! Incrível.

No entanto, e eu nunca tentei isso antes - pensei em melhorar ainda mais com o OPTION (OPTIMIZE FOR @p0 = '4/1/2021').

Eu esperava que isso também usasse a busca, mas sem a necessidade de recompilação toda vez. Eu apenas alteraria periodicamente a data passada para OPTIMIZE FOR - talvez para o início do mês anterior.

No entanto, esta é a consulta no repositório de consultas.

insira a descrição da imagem aqui

E ele faz uma varredura completa de mais de 1 milhão de linhas ao definir o parâmetro de data para 7/4/21!

Então agora estou perdido. Eu tentei ler sobre tudo o que posso sobre o assunto, mas não encontrei esse problema. RECOMPILE funciona, mas OPTIMIZE FOR não parece fazer nada quando espero que simule efetivamente a execução da consulta no SSMS com valores codificados.

Planos de consulta

Este primeiro plano é o único plano inesperado - é uma varredura e eu quero uma busca.

OTIMIZE PARA @p1 = '2021/4/1' - https://www.brentozar.com/pastetheplan/?id=H1JB43AUu OTIMIZE PARA AMBOS OS PARAM - https://www.brentozar.com/pastetheplan/?id=rkV9U3AUu OPÇÃO RECOMPILAR - https://www.brentozar.com/pastetheplan/?id=SJ5cS3CUd

Estes são para provar que o otimizador sabe que datas recentes devem ser procuradas!

HARDCODED 2013 - SCAN - https://www.brentozar.com/pastetheplan/?id=BkeA42RLu HARDCODED 2015 - BUSCA - https://www.brentozar.com/pastetheplan/?id=S1c8r3R8O

Estou começando a me perguntar se esta versão não suporta OPTIMIZE FOR, mesmo que não encontre nada dizendo que não seria


Edit: (Após a resposta de Paul)

Eu tentei algumas coisas adicionais. Primeiro aqui está a definição de VIEW que não incluí antes. Isso faz um JOIN e, como usa SCHEMABINDING, o otimizador pode substituí-lo:

CRIAR VISUALIZAÇÃO [dbo].[Helper_PackageVerification] COM SCHEMABINDING AS

SELECIONAR

-- Colunas de verificação do pacote [t0].PackageVerificationId, [t0].Verfied, -- erro de ortografia de muito tempo atrás! [t0].VerifyDate, -- isso não é anulável em [t0] btw [t0]. Nome de usuário,

-- Colunas do pacote [t1].PackageId, [t1].PackageStatus, [t1].PackedOnDate

FROM [dbo].[PackageVerification] AS [t0]
INNER JOIN [dbo].[Package] AS [t1] ON [t1].[PackageId] = [t0].[PackageId]

WHERE (Verfied = 1 E VerifyDate NÃO É NULO E PackageStatus <> 99) GO

O índice CLUSTERED está ativado PackageVerificationIde o índice principal NON CLUSTERED é mostrado acima. Na verdade, criei meia dúzia de índices de conversão para ver qual escolheria.

  1. Eu codifiquei PackageStatus <> 99. Originalmente era um parâmetro.

  2. Tentei adicionar NOT NULL ao filtro na exibição para ver o que aconteceria. Isso realmente me deu um SEEK, mas um inútil, já que o predicado SEEK estava realmente em VerifyDate IS NOT NULL.

https://www.brentozar.com/pastetheplan/?id=r1HlgF1Dd

Você não pode adicionar um índice filtrado a uma exibição indexada, portanto, mesmo que a exibição filtre as datas NOT NULL, provavelmente não poderá ser correspondida. Então essa poderia ser a razão principal pela qual eu não consegui que minha data fosse usada para o predicado SEEK?

  1. Nesse caso, não tentei usar o índice auxiliar diretamente na consulta, mas esperaria que funcionasse com NOEXPAND, pois estou fazendo isso em outro lugar.
sql-server execution-plan
  • 1 1 respostas
  • 111 Views

1 respostas

  • Voted
  1. Best Answer
    Paul White
    2021-04-23T01:40:25+08:002021-04-23T01:40:25+08:00

    Usar OPTIMIZE FORnão é o mesmo que OPTION (RECOMPILE). O primeiro usa valores de parâmetro fornecidos na estimativa de cardinalidade para um plano que pode ser reutilizado com outros valores de parâmetro . A opção recompile incorpora o valor do parâmetro de tempo de execução e produz um plano descartável que nunca será reutilizado .

    O OPTIMIZE FORplano, portanto, precisa garantir a operação correta para todos os valores possíveis. O plano de recompilação pode usar otimizações adicionais que são válidas apenas para o valor presente. Ele também pode usar otimizações que só funcionam com valores literais, por exemplo, empurrando um filtro após uma função de janela.

    Isso importa no seu caso porque quando o OPTIMIZE FORplano corresponde à exibição indexada, ele adiciona IS NOT NULLpredicados residuais adicionais em VerifyDate e PackageStatus :

    insira a descrição da imagem aqui

    O plano de recompilação pode remover essa lógica porque os valores fornecidos não são nulos. A presença desses predicados implícitos extras é suficiente para impedir a correspondência de índice para uma busca. Geralmente, é melhor garantir que as colunas de origem sejam restritas para não serem nulas ou rejeitadas explicitamente na definição de exibição indexada para minimizar esse tipo de coisa.

    Agora, o otimizador tem uma ampla variedade de opções de planos para suas consultas. Uma indicação disso é o número de objetos de estatísticas carregados - 17. Pequenas diferenças no caminho percorrido pelo otimizador podem produzir resultados diferentes.

    A correspondência automática de visualizações indexadas é um recurso interessante, tecnicamente, mas tem limitações. O SQL Server precisa adicionar algumas coisas e aplicar reescritas específicas para obter correspondência, o que pode ter efeitos colaterais inesperados (observe o predicado @p1 invertido acima). O plano pós-correspondência também nem sempre é completamente limpo para corresponder ao que uma consulta escrita na exibição produziria. Estes não são bugs, apenas detalhes de implementação.

    Eu normalmente aconselho as pessoas a escrever consultas diretamente na visão e especificar uma NOEXPANDdica, onde isso for prático. Você pode descobrir que testar suas consultas escritas dessa maneira produziria os resultados que você está procurando.

    Artigos relacionados que escrevi:

    • Sniffing, Embedding e Opções de RECOMPILE de Parâmetros
    • Visualizações e estatísticas indexadas
    • Outro motivo para usar dicas NOEXPAND na Enterprise Edition
    • 4

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve