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 / 130751
Accepted
Royi Namir
Royi Namir
Asked: 2016-02-29 22:24:55 +0800 CST2016-02-29 22:24:55 +0800 CST 2016-02-29 22:24:55 +0800 CST

Índice SEEK não é usado a menos que OPTION (RECOMPILE)?

  • 772

(Pergunta movida do SO)

Eu tenho uma tabela (dados fictícios) com índice clusterizado contém 2 colunas:

insira a descrição da imagem aqui

Agora eu executo essas duas consultas:

declare 
@productid int =1 , 
@priceid  int = 1




SELECT productid,
       t.priceID
FROM   Transactions AS t
WHERE  (productID = @productid OR @productid IS NULL)
       AND (priceid = @priceid OR @priceid IS NULL)  


SELECT productid,
       t.priceID
FROM   Transactions AS t
WHERE  (productID = @productid)
       AND (priceid = @priceid)

O plano de execução real para ambas as consultas é:

insira a descrição da imagem aqui

Como você pode ver, o primeiro está usando SCAN enquanto o segundo está usando SEEK.

No entanto - adicionando OPTION (RECOMPILE)à primeira consulta , fez o plano de execução também usar SEEK :

insira a descrição da imagem aqui

Amigos no bate-papo do DBA me disseram que:

Em sua consulta, @productid=1, o que significa que (productID=@productID OU @productID IS NULL) pode ser simplificado para (productID=@productID). O primeiro requer uma varredura para funcionar com qualquer valor de @productID, o último pode usar uma busca. Então, quando você usa RECOMPILE, o SQL Server vai olhar qual valor você realmente tem em @productID e fazer o melhor plano para isso. Com um valor não nulo em @productID, uma busca é melhor. Se o valor de @productID for desconhecido, o plano deve se adequar a qualquer valor possível em @productID, o que exigiria uma varredura. Esteja avisado: OPTION (RECOMPILE) forçará uma recompilação do plano toda vez que você executá-lo, o que adicionará alguns milissegundos a cada execução. Embora isso seja apenas um problema se a consulta for executada com muita frequência.

Também :

Se @productID for nulo, qual valor você procuraria? Resposta: não há nada para buscar. Todos os valores se qualificam.

Eu entendo que OPTION (RECOMPILE)força o SQL Server a ver quais valores reais os parâmetros têm e ver se ele pode SEEK com ele.

Mas agora perco o benefício da compilação antecipada.

Pergunta

IMHO-SCAN só ocorrerá se um parâmetro for nulo.
Tudo bem - deixe o SQL SERVER criar um plano de execução para SCAN.
MAS se o SQL Server vê que eu executo essa consulta muitas vezes com valores: 1,1, então por que ele não cria OUTRO plano de execução e usa SEEK para isso?

AFAIK-SQL cria plano de execução para as consultas mais acessadas .

  • Por que o SQL SERVER não salva um plano de execução para:

    @productid int =1 , @priceid int = 1

(Eu corro muitas vezes com esses valores)

  • É possível forçar o SQL a manter esse plano de execução (que usa SEEK) - para invocação futura?

Script completo de criação de tabela + dados

index sql-server-2008-r2
  • 1 1 respostas
  • 581 Views

1 respostas

  • Voted
  1. Best Answer
    Paul White
    2016-03-01T05:01:23+08:002016-03-01T05:01:23+08:00

    Resumindo alguns dos principais pontos de nossa discussão na sala de bate-papo :


    De um modo geral, o SQL Server armazena em cache um único plano para cada instrução . Esse plano deve ser válido para todos os possíveis valores de parâmetros futuros .

    Não é possível armazenar em cache um plano de busca para sua consulta, porque esse plano não seria válido se, por exemplo, @productid fosse nulo.

    Em alguma versão futura, o SQL Server pode oferecer suporte a um único plano que escolhe dinamicamente entre uma varredura e uma busca, dependendo dos valores dos parâmetros de tempo de execução, mas isso não é algo que temos hoje.

    Classe de problema geral

    Sua consulta é um exemplo de um padrão conhecido como consulta "pega tudo" ou "pesquisa dinâmica". Existem várias soluções, cada uma com suas vantagens e desvantagens. Nas versões modernas do SQL Server (2008+), as principais opções são:

    • IFblocos
    • OPTION (RECOMPILE)
    • SQL dinâmico usandosp_executesql

    O trabalho mais abrangente sobre o assunto é provavelmente o de Erland Sommarskog, incluído nas referências no final desta resposta. Não há como fugir das complexidades envolvidas, por isso é necessário investir algum tempo experimentando cada opção para entender os trade-offs em cada caso.

    IFblocos

    Para ilustrar uma IFsolução de bloco para o caso específico da questão:

    IF @productid IS NOT NULL AND @priceid IS NOT NULL
    BEGIN
        SELECT 
            T.productID,
            T.priceID
        FROM dbo.Transactions AS T
        WHERE
            T.productID = @productid
            AND T.priceID = @priceid;
    END;
    ELSE IF @productid IS NOT NULL
    BEGIN
        SELECT 
            T.productID,
            T.priceID
        FROM dbo.Transactions AS T
        WHERE
            T.productID = @productid;
    END;
    ELSE IF @priceid IS NOT NULL
    BEGIN
        SELECT 
            T.productID,
            T.priceID
        FROM dbo.Transactions AS T
        WHERE
            T.priceID = @priceid;
    END;
    ELSE
    BEGIN
        SELECT 
            T.productID,
            T.priceID
        FROM dbo.Transactions AS T;
    END;
    

    Isso contém uma instrução separada para os quatro possíveis casos nulos ou não nulos para cada um dos dois parâmetros (ou variáveis ​​locais), portanto, há quatro planos.

    Há um problema potencial com a detecção de parâmetros, que pode exigir uma OPTIMIZE FORdica em cada consulta. Consulte a seção de referências para explorar esses tipos de sutilezas.

    recompilar

    Conforme observado acima e na pergunta, você também pode adicionar uma OPTION (RECOMPILE)dica para obter um novo plano (busca ou varredura) em cada invocação. Dada a frequência relativamente lenta de chamadas no seu caso (uma vez a cada dez segundos, em média, com um tempo de compilação abaixo de um milissegundo), parece provável que esta opção seja adequada para você:

    SELECT
        T.productID,
        T.priceID
    FROM dbo.Transactions AS T
    WHERE
        (T.productID = @productid OR @productid IS NULL)
        AND (T.priceID = @priceid OR @priceid IS NULL)
    OPTION (RECOMPILE);
    

    Também é possível combinar recursos das opções acima de forma criativa, para aproveitar ao máximo as vantagens de cada método, minimizando as desvantagens. Realmente não há atalho para entender essas coisas em detalhes e, em seguida, fazer uma escolha informada apoiada por testes realistas.

    Leitura adicional

    • Parâmetro Sniffing, Incorporação e as RECOMPILEOpções
    • Condições de pesquisa dinâmica em T-SQL por Erland Sommarskog
    • Procedimentos de alta performance por Kimberly Tripp
    • 10

relate perguntas

  • Como criar várias entradas no índice com base nos campos de uma linha?

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

  • Quanto "Padding" coloco em meus índices?

  • O que significa "índice" em RDBMSs? [fechado]

  • Como criar um índice condicional no MySQL?

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