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 / 140247
Accepted
Geoff Patterson
Geoff Patterson
Asked: 2016-06-03 08:40:12 +0800 CST2016-06-03 08:40:12 +0800 CST 2016-06-03 08:40:12 +0800 CST

Por que o operador de concatenação estima menos linhas do que suas entradas?

  • 772

No trecho de plano de consulta a seguir, parece óbvio que a estimativa de linha para o Concatenationoperador deve ser ~4.3 billion rows, ou a soma das estimativas de linha para suas duas entradas.

No entanto, uma estimativa de ~238 million rowsé produzida, levando a uma estratégia Sort/ abaixo do ideal Stream Aggregateque derrama centenas de GB de dados em tempdb. Uma estimativa logicamente consistente neste caso teria produzido um Hash Aggregate, removido o derramamento e melhorado drasticamente o desempenho da consulta.

Isso é um bug no SQL Server 2014? Existem circunstâncias válidas nas quais uma estimativa menor do que as entradas poderia ser razoável? Que soluções alternativas podem estar disponíveis?

insira a descrição da imagem aqui

Aqui está o plano de consulta completo (anônimo). Não tenho acesso de administrador de sistema a este servidor para fornecer saídas QUERYTRACEON 2363ou sinalizadores de rastreamento semelhantes, mas posso obter essas saídas de um administrador se forem úteis.

O banco de dados está no nível de compatibilidade 120 e, portanto, está usando o novo Estimador de cardinalidade do SQL Server 2014.

As estatísticas são atualizadas manualmente toda vez que os dados são carregados. Dado o volume de dados, estamos usando a taxa de amostragem padrão. É possível que uma taxa de amostragem mais alta (ou FULLSCAN) possa ter um impacto.

sql-server performance
  • 2 2 respostas
  • 817 Views

2 respostas

  • Voted
  1. Best Answer
    Paul White
    2016-06-03T14:33:25+08:002016-06-03T14:33:25+08:00

    Para citar Campbell Fraser neste item do Connect :

    Essas "inconsistências de cardinalidade" podem surgir em várias situações, inclusive quando concat é usado. Eles podem surgir porque a estimativa de uma subárvore específica no plano final pode ter sido realizada em uma subárvore estruturada de forma diferente, mas logicamente equivalente. Devido à natureza estatística da estimativa de cardinalidade, estimar em árvores diferentes, mas logicamente equivalentes, não garante obter a mesma estimativa. Portanto, no geral, nenhuma garantia de consistência esperada é fornecida.

    Para expandir um pouco: A maneira que gosto de explicar é dizer que a estimativa de cardinalidade inicial (realizada antes do início da otimização baseada em custo) produz estimativas de cardinalidade mais "consistentes", pois toda a árvore inicial é processada, com cada subseqüente estimativa dependente diretamente da anterior.

    Durante a otimização baseada em custo, partes da árvore do plano (um ou mais operadores) podem ser exploradas e substituídas por alternativas, cada uma das quais pode exigir uma nova estimativa de cardinalidade. Não há uma maneira geral de dizer qual estimativa será geralmente melhor do que outra, então é bem possível acabar com um plano final que parece "inconsistente". Isso é simplesmente o resultado de costurar "pedaços de planos" para formar o arranjo final.

    Dito isso, houve algumas alterações detalhadas no novo estimador de cardinalidade (CE) introduzido no SQL Server 2014 que torna isso um pouco menos comum do que no caso do CE original.

    Além de atualizar para a atualização cumulativa mais recente e verificar se as correções do otimizador com 4199 estão ativadas, suas principais opções são tentar alterações de estatísticas/índice (observando os avisos de índices ausentes) e atualizações ou expressar a consulta de maneira diferente. O objetivo é adquirir um plano que exiba o comportamento que você precisa. Isso pode ser congelado com um guia de plano, por exemplo.

    O plano anônimo dificulta a avaliação dos detalhes, mas também examinaria cuidadosamente os bitmaps para ver se eles são do tipo 'otimizado' (Opt_Bitmap) ou pós-otimização (Bitmap). Também desconfio dos Filtros.

    Se as contagens de linhas forem precisas, isso parece uma consulta que pode se beneficiar de columnstore. Além dos benefícios usuais, você pode aproveitar a concessão de memória dinâmica para operadores de modo de lote ( o sinalizador de rastreamento 9389 pode ser necessário).

    • 21
  2. Hannah Vernon
    2016-06-03T09:34:26+08:002016-06-03T09:34:26+08:00

    Construir um banco de teste reconhecidamente bastante simples no SQL Server 2012 (11.0.6020) me permite recriar um plano com duas consultas combinadas de hash sendo concatenadas por meio de um arquivo UNION ALL. Meu test-bed não exibe a estimativa incorreta que você vê. Talvez este seja um problema do SQL Server 2014 CE.

    Obtenho uma estimativa de 133.785 linhas para uma consulta que na verdade retorna 280 linhas, no entanto, isso é esperado, como veremos mais adiante:

    IF OBJECT_ID('dbo.Union1') IS NOT NULL
    DROP TABLE dbo.Union1;
    CREATE TABLE dbo.Union1
    (
        Union1_ID INT NOT NULL
            CONSTRAINT PK_Union1
            PRIMARY KEY CLUSTERED
            IDENTITY(1,1)
        , Union1_Text VARCHAR(255) NOT NULL
        , Union1_ObjectID INT NOT NULL
    );
    
    IF OBJECT_ID('dbo.Union2') IS NOT NULL
    DROP TABLE dbo.Union2;
    CREATE TABLE dbo.Union2
    (
        Union2_ID INT NOT NULL
            CONSTRAINT PK_Union2
            PRIMARY KEY CLUSTERED
            IDENTITY(2,2)
        , Union2_Text VARCHAR(255) NOT NULL
        , Union2_ObjectID INT NOT NULL
    );
    
    INSERT INTO dbo.Union1 (Union1_Text, Union1_ObjectID)
    SELECT o.name, o.object_id
    FROM sys.objects o;
    
    INSERT INTO dbo.Union2 (Union2_Text, Union2_ObjectID)
    SELECT o.name, o.object_id
    FROM sys.objects o;
    GO
    
    SELECT *
    FROM dbo.Union1 u1
        INNER HASH JOIN sys.objects o ON u1.Union1_ObjectID = o.object_id
    UNION ALL
    SELECT *
    FROM dbo.Union2 u2
        INNER HASH JOIN sys.objects o ON u2.Union2_ObjectID = o.object_id;
    

    Acho que o motivo é a falta de estatísticas para as duas junções resultantes que são UNIONed. O SQL Server precisa fazer suposições fundamentadas na maioria dos casos em torno da seletividade das colunas quando confrontado com a falta de estatísticas.

    Joe Sack tem uma leitura interessante sobre isso aqui .

    Para um UNION ALL, é seguro dizer que veremos exatamente o número total de linhas retornadas por cada componente da união, no entanto, como o SQL Server está usando estimativas de linha para os dois componentes do UNION ALL, vemos que ele adiciona o total de linhas estimadas de ambos consultas para obter a estimativa para o operador de concatenação.

    No meu exemplo acima, o número estimado de linhas para cada parte do UNION ALLé 66,8927, que quando somado é igual a 133,785, que vemos para o número estimado de linhas para o operador de concatenação.

    O plano de execução real para a consulta união acima se parece com:

    insira a descrição da imagem aqui

    Você pode ver o número "estimado" vs "real" de linhas. No meu caso, adicionar o número "estimado" de linhas retornadas pelos dois operadores de correspondência de hash é exatamente igual ao valor mostrado pelo operador de concatenação.

    Eu tentaria obter a saída do rastreamento 2363 etc, conforme recomendado na postagem de Paul White que você mostra em sua pergunta. Como alternativa, você pode tentar usar OPTION (QUERYTRACEON 9481)na consulta para reverter para a versão 70 CE para ver se isso "corrige" o problema.

    • 7

relate perguntas

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

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

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

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