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 / 260639
Accepted
Data Dill
Data Dill
Asked: 2020-02-27 07:13:16 +0800 CST2020-02-27 07:13:16 +0800 CST 2020-02-27 07:13:16 +0800 CST

Por que esse proc armazenado causa uma varredura de índice clusterizado, mas procura ao usar OPTION RECOMPILE?

  • 772

Acho que posso saber a resposta com base em minha pesquisa, mas estou procurando confirmação de como/por que o mecanismo compila o plano da maneira que faz com

Parâmetros sendo passados: @ID int ,@OtherID INT

SELECT  b.Column1
        ,b.Column2
        ,b.Column3
        ,b.Column4
        ,b.Column5
        ,c.Column1
        ,b.Column1
        ,e.Column1
FROM    Table1 AS b 
        inner join Table2 AS t
        on b.ID = t.ID
        left join [LINKED SERVER].[DB].dbo.Table3 as c
        on b.ID = c.ID
        left join Table4 AS e
        on b.ID= e.ID
where   (b.ID = @ID or @ID= 0)
        And b.ID = @OtherID
        And b.ID IS NOT NULL
        and e.ID = 1

Agora eu determinei que a causa da varredura de índice é por causa desta linha: where (b.ID = @ID or @ID= 0). Mais especificamente, @ID = 0. Para esclarecer ainda mais, 0 para esse campo de ID não existe como um valor na tabela subjacente, foi simplesmente algo que um desenvolvedor fez para permitir que um usuário recuperasse todos os resultados passando 0 para o parâmetro e, em seguida, verificando se esse parâmetro é 0, como resultado, mais linhas são puxadas de volta (normalmente, você retornaria apenas 1-3 resultados).

Agora, o que é extremamente estranho, é que se eu adicionar OPTION RECOMPILE, o mecanismo é capaz de criar um plano muito melhor ao custo de sobrecarga (tempo de compilação), é claro:

insira a descrição da imagem aqui

O que eu gostaria de saber é como isso é possível. Pelo que li online, usando OPTION RECOMPILE, o mecanismo substituirá literalmente o valor pelo valor real passado para o parâmetro e pode ver muito facilmente que @ID 1234 não é igual a 0. No entanto, se você não usar OPTION RECOMPILEo mecanismo pegará o número total de registros, que é 120.000, e o dividirá pelo número total de possibilidades distintas, 107.000. Isso resulta em cerca de 1,1 linhas estimadas sendo retornadas e confirmei isso observando as propriedades estimadas do plano que tem a verificação de índice, mas por que o mecanismo continuaria a verificação de índice se a estimativa estiver correta? Até atualizei as estatísticas só para ter certeza.

insira a descrição da imagem aqui

sql-server optimization
  • 2 2 respostas
  • 139 Views

2 respostas

  • Voted
  1. Best Answer
    Paul White
    2020-02-27T21:30:01+08:002020-02-27T21:30:01+08:00
    b.ID = @ID OR @ID = 0
    

    O otimizador precisa produzir um plano com uma varredura de índice, porque o plano é armazenado em cache e reutilizado .

    Em uma execução subsequente, o parâmetro @IDpode ser zero. Uma busca de índice não tem valor nesse caso, porque não há IDvalor a ser buscado. Outras vezes, haverá um valor diferente de zero fornecido para @ID, mas o plano em cache precisa funcionar corretamente para todos os valores de parâmetro possíveis.

    Quando OPTION (RECOMPILE)é usado, a Otimização de Incorporação de Parâmetros (PEO) significa que o valor atual para @IDé usado no lugar do parâmetro em cada execução e nenhum plano é armazenado em cache.

    Digamos @IDque seja 1234. Após PEO, o otimizador vê:

    b.ID = 1234 OR 1234 = 0
    

    Isso é simplificado pela lógica de detecção de contradição para:

    b.ID = 1234
    

    ...que permite uma busca em ID.

    Para ler mais, consulte meu artigo Parameter Sniffing, Embedding, and the RECOMPILE Options .

    • 2
  2. Denis Rubashkin
    2020-02-27T07:24:51+08:002020-02-27T07:24:51+08:00

    Seu problema é condição opcional(b.ID = @ID or @ID= 0)

    Se você não quiser usar OPTION(RECOMPILE), você deve dividir sua consulta na condição:

    IF @ID = 0 BEGIN
        SELECT b.Column1, 
               b.Column2, 
               b.Column3, 
               b.Column4, 
               b.Column5, 
               c.Column1, 
               b.Column1, 
               e.Column1
        FROM Table1 AS b
             INNER JOIN Table2 AS t ON b.ID = t.ID
             LEFT JOIN [LINKED SERVER].[DB].dbo.Table3 AS c ON b.ID = c.ID
             LEFT JOIN Table4 AS e ON b.ID = e.ID
        WHERE b.ID = @OtherID
              AND b.ID IS NOT NULL
              AND e.ID = 1;
    END ELSE BEGIN
        SELECT b.Column1, 
               b.Column2, 
               b.Column3, 
               b.Column4, 
               b.Column5, 
               c.Column1, 
               b.Column1, 
               e.Column1
        FROM Table1 AS b
             INNER JOIN Table2 AS t ON b.ID = t.ID
             LEFT JOIN [LINKED SERVER].[DB].dbo.Table3 AS c ON b.ID = c.ID
             LEFT JOIN Table4 AS e ON b.ID = e.ID
        WHERE b.ID = @ID
              AND b.ID = @OtherID
              AND b.ID IS NOT NULL
              AND e.ID = 1;
    END
    
    • 1

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