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 / 234096
Accepted
dsuy
dsuy
Asked: 2019-04-07 09:04:07 +0800 CST2019-04-07 09:04:07 +0800 CST 2019-04-07 09:04:07 +0800 CST

Valores diretos no predicado produzem um plano não tão bom

  • 772

Estou usando o dump do StackOverflow para executar alguns testes.

Em particular, estou consultando esta tabela:

Tabela de postagens

Eu criei este índice:

Índice criado

Estou executando a seguinte consulta (apenas forçando um índice para testar alternativas)

Consulta com valores diretos

Eu recebo o seguinte plano executivo com um custo alto (66,63).

Plano não tão bom

Estas são as estatísticas de IO depois de executar esta consulta:

insira a descrição da imagem aqui

Em seguida, executo a mesma consulta fornecendo variáveis ​​em vez de valores diretos

Consulta com variáveis

Eu recebo um plano melhor (Custo é 0,4385).

Melhor plano

As estatísticas também são melhores:

Estatísticas melhores

A princípio... pensei que o SQL Server não estava reconhecendo valores diretos como INT, mas não há incompatibilidade de tipo nem avisos de conversão implícitos.

Também tentei evitar o paralelismo, mas ainda recebo um plano de alto custo (e estatísticas de E/S mais altas) com MAXDOP 1 ao passar valores diretos no predicado.

Ao comparar os dois planos, existem estimativas diferentes:

insira a descrição da imagem aqui

O que há de errado com valores diretos sendo passados ​​como parte do predicado?

sql-server sql-server-2012
  • 1 1 respostas
  • 129 Views

1 respostas

  • Voted
  1. Best Answer
    Josh Darnell
    2019-04-09T05:14:02+08:002019-04-09T05:14:02+08:00

    O que há de errado com valores diretos sendo passados ​​como parte do predicado?

    A diferença entre variáveis ​​e parâmetros

    O otimizador usa o vetor de densidade estatística ao calcular estimativas para variáveis.

    Quando valores "diretos" ou "estáticos" são incorporados na consulta diretamente, o histograma de estatísticas é usado. É por isso que você obtém estimativas diferentes e, portanto, planos diferentes.

    Aqui está meu plano estimado: https://www.brentozar.com/pastetheplan/?id=SJCduTuKN

    Na minha cópia de 2010 do banco de dados SO, a densidade da coluna OwnerUserId é 0,000003807058. Multiplicando isso por 3.744.192 linhas = 14,2544 linhas. Que é exatamente o número de linhas estimado para sair de IX_Posts_OwnerUserId.

    captura de tela da estimativa de busca de índice

    Você pode obter essas informações sobre as estatísticas desse índice executando este comando DBCC:

    DBCC SHOW_STATISTICS('dbo.Posts', 'IX_Posts_OwnerUserId');
    

    Aqui está a saída (abreviada):

    Name                    Updated             Rows
    IX_Posts_OwnerUserId    Apr  8 2019  8:33AM 3744192
    
    All density     Average Length  Columns
    3.807058E-06    4               OwnerUserId
    

    Como PostTypeId também faz parte da cláusula WHERE, as estatísticas também são geradas automaticamente para essa coluna. Esse vetor de densidade resulta em 0,25 x 3.744.192 linhas = 936.048 linhas.

    DBCC SHOW_STATISTICS('dbo.Posts', '_WA_Sys_00000010_0519C6AF');
    

    E a saída:

    Name                        Updated             Rows
    _WA_Sys_00000010_0519C6AF   Apr  8 2019  9:04AM 3744192
    
    All density Average Length  Columns
    0.25        4               PostTypeId
    

    Como esse é um predicado "E", a estimativa usa o menor dos dois.

    Quando você usa valores estáticos em vez de variáveis, ele usa o histograma de estatísticas. Isso está no terceiro conjunto de resultados desse comando SHOW_STATISTICS. Para a chave que você está usando, aqui está a entrada do histograma:

    RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
    22656           13040       11371   305                 42.7541
    

    É daí que vem a estimativa de 11.371 no plano de "valores estáticos".

    O histograma pode ser uma estimativa melhor na maioria das vezes, pois lida um pouco melhor com casos extremos - já que geralmente haverá alguns valores discrepantes em uma tabela grande como essa.

    Diferenças de custo

    Nesse caso específico, o histograma produz uma estimativa exatamente correta. O custo do plano produzido é (corretamente) superior ao que utiliza o vetor densidade, pois tem que processar muito mais linhas.

    O plano de "menor custo" pensa que 14 linhas serão produzidas por essa busca, quando na verdade 11.371 linhas são produzidas.

    Leituras Lógicas

    As leituras lógicas são um pouco maiores no plano paralelo devido à pré- busca de loops aninhados . Não parece fazer uma grande diferença na minha máquina - o tempo decorrido para as consultas estava dentro de 10 ms uma da outra.

    O paralelismo na verdade não ajuda em nada, já que todas as linhas terminam em um thread (na minha máquina de qualquer maneira). Adicionar OPTION (MAXDOP 1)ajuda no tempo de execução, mas não remove as leituras lógicas extras.

    Uma solução potencial para o problema de "leituras extras" para essa consulta seria evitar totalmente a pesquisa de chave adicionando PostTypeId como uma coluna incluída:

    CREATE INDEX IX_Posts_OwnerUserId ON dbo.Posts (OwnerUserId) 
    INCLUDE (PostTypeId) 
    WITH (DROP_EXISTING = ON);
    
    • 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