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 / 20597
Accepted
Justin Grant
Justin Grant
Asked: 2012-07-10 11:15:22 +0800 CST2012-07-10 11:15:22 +0800 CST 2012-07-10 11:15:22 +0800 CST

Como o SQL Server sabe que os predicados estão correlacionados?

  • 772

Ao diagnosticar consultas do SQL Server 2008 R2 com estimativa de cardinalidade ruim (apesar da indexação simples, estatísticas atualizadas etc. ) que contém predicados AND correlacionados no SQL Server 2008 ou no SQL Server 2008 R2 ou no SQL Server 2012

Posso adivinhar o que o artigo da KB quer dizer com "correlacionado", por exemplo, predicado nº 2 e predicado nº 1, em grande parte, visam as mesmas linhas.

Mas não sei como o SQL Server sabe dessas correlações. Uma tabela precisa de um índice de várias colunas contendo colunas de ambos os predicados? O SQL usa estatísticas para verificar se os valores de uma coluna estão correlacionados com outra? Ou algum outro método é usado?

Estou perguntando isso por dois motivos:

  1. para determinar quais das minhas tabelas e consultas podem ser melhoradas usando este hotfix
  2. para saber o que devo fazer na indexação, estatísticas, etc. para afetar #1
sql-server sql-server-2008-r2
  • 1 1 respostas
  • 1708 Views

1 respostas

  • Voted
  1. Best Answer
    Paul White
    2013-07-31T00:08:21+08:002013-07-31T00:08:21+08:00

    Considere a consulta simples do AdventureWorks e o plano de execução mostrado abaixo. A consulta contém predicados conectados com AND. A estimativa de cardinalidade do otimizador é de 41.211 linhas:

    -- Estimate 41,211 rows
    SELECT COUNT_BIG(*)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.TransactionID BETWEEN 100000 AND 168336
        AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
    

    Plano de execução padrão

    Usando estatísticas padrão

    Dadas apenas estatísticas de coluna única, o otimizador produz essa estimativa estimando a cardinalidade para cada predicado separadamente e multiplicando as seletividades resultantes juntas. Esta heurística assume que os predicados são completamente independentes.

    Dividir a consulta em duas partes facilita a visualização do cálculo:

    -- Estimate 68,336.4 rows
    SELECT COUNT_BIG(*)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.TransactionID BETWEEN 100000 AND 168336;
    

    A tabela Histórico de transações contém 113.443 linhas no total, portanto, a estimativa de 68.336,4 representa uma seletividade de 68336,4/113443 = 0,60238533 para esse predicado. Essa estimativa é obtida usando as informações do histograma para a TransactionIDcoluna e os valores constantes especificados na consulta.

    -- Estimate 68,413 rows
    SELECT COUNT_BIG(*)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
    

    Este predicado tem uma seletividade estimada de 68413,0/113443 = 0,60306056 . Novamente, é calculado a partir dos valores constantes do predicado e do histograma do TransactionDateobjeto de estatísticas.

    Assumindo que os predicados são completamente independentes, podemos estimar a seletividade dos dois predicados juntos, multiplicando-os. A estimativa de cardinalidade final é obtida multiplicando a seletividade resultante pelas 113.443 linhas na tabela base:

    0,60238533 * 0,60306056 * 113443 = 41210,987

    Após o arredondamento, esta é a estimativa de 41.211 vista na consulta original (o otimizador também usa matemática de ponto flutuante internamente).

    Não é uma boa estimativa

    As colunas TransactionIDe TransactionDatetêm uma correlação próxima no conjunto de dados AdventureWorks (como as chaves e as colunas de data que aumentam monotonicamente costumam fazer). Essa correlação significa que a suposição de independência é violada. Como consequência, o plano de consulta pós-execução mostra 68.095 linhas em vez das 41.211 estimadas:

    Plano de pós-execução

    Sinalizador de rastreamento 4137

    A ativação desse sinalizador de rastreamento altera a heurística usada para combinar predicados. Em vez de assumir total independência, o otimizador considera que as seletividades dos dois predicados são próximas o suficiente para que possam ser correlacionadas:

    -- Estimate 68,336.4
    SELECT COUNT_BIG(*)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.TransactionID BETWEEN 100000 AND 168336
        AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
    OPTION (QUERYTRACEON 4137);
    

    Lembre-se de que o TransactionIDpredicado sozinho estimou 68.336,4 linhas e o TransactionDatepredicado sozinho estimou 68.413 linhas. O otimizador escolheu a menor dessas duas estimativas em vez de multiplicar as seletividades.

    Esta é apenas uma heurística diferente, é claro, mas que pode ajudar a melhorar as estimativas para consultas com ANDpredicados correlacionados. Cada predicado é considerado para uma possível correlação, e há outros ajustes feitos quando muitas ANDcláusulas estão envolvidas, mas esse exemplo serve para mostrar o básico disso.

    O equivalente ao sinalizador de rastreamento 4137 no estimador de cardinalidade atual é a ASSUME_MIN_SELECTIVITY_FOR_FILTER_ESTIMATES dica de consulta .

    Faz com que o SQL Server gere um plano usando seletividade mínima ao estimar os predicados AND para os filtros para contabilizar a correlação total. Esse nome de dica é equivalente ao sinalizador de rastreamento 4137 quando usado com o modelo de estimativa de cardinalidade do SQL Server 2012 (11.x) e versões anteriores e tem efeito semelhante quando o sinalizador de rastreamento 9471 é usado com o modelo de estimativa de cardinalidade do SQL Server 2014 (12.x ) ou mais alto.

    Estatísticas de várias colunas

    Isso pode ajudar em consultas com correlações, mas as informações do histograma ainda são baseadas apenas na coluna inicial das estatísticas. As seguintes estatísticas candidatas de várias colunas, portanto, diferem de maneira importante:

    CREATE STATISTICS
        [stats Production.TransactionHistory TransactionID TransactionDate]
    ON Production.TransactionHistory
        (TransactionID, TransactionDate);
    
    CREATE STATISTICS
        [stats Production.TransactionHistory TransactionDate TransactionID]
    ON Production.TransactionHistory
        (TransactionDate, TransactionID);
    

    Tomando apenas um deles, podemos ver que a única informação extra são os níveis extras da densidade 'todos'. O histograma ainda contém apenas informações detalhadas sobre a TransactionDatecoluna.

    DBCC SHOW_STATISTICS
        (
            'Production.TransactionHistory', 
            'stats Production.TransactionHistory TransactionDate TransactionID'
        );
    

    Estatísticas de várias colunas

    Com essas estatísticas de várias colunas no lugar...

    SELECT COUNT_BIG(*)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.TransactionID BETWEEN 100000 AND 168336
        AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
    

    ...o plano de execução mostra uma estimativa que é exatamente a mesma de quando apenas as estatísticas de coluna única estavam disponíveis:

    Plano de estatísticas de várias colunas

    • 20

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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