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 / 148523
Accepted
jesijesi
jesijesi
Asked: 2016-09-02 01:18:07 +0800 CST2016-09-02 01:18:07 +0800 CST 2016-09-02 01:18:07 +0800 CST

Estimativa de cardinalidade para >= e > para valor estatístico intra-etapa

  • 772

Estou tentando entender como o SQL Server tenta estimar as cláusulas 'maior que' e 'maior que igual a' no SQL Server 2014.

Acho que entendo a estimativa de cardinalidade quando atinge a etapa, por exemplo, se eu entender

    select * from charge where charge_dt >= '1999-10-13 10:47:38.550'

A estimativa de cardinalidade é 6672, que pode ser facilmente calculada como 32(EQ_ROWS) + 6624(RANGE_ROWS) + 16 (EQ_ROWS) = 6672 (histograma na captura de tela abaixo)

insira a descrição da imagem aqui

Mas quando eu faço

    select * from charge where charge_dt >= '1999-10-13 10:48:38.550' 

(aumentei o tempo para 10:48, então não é um passo)

a estimativa é 4844,13.

Como isso é calculado?

sql-server sql-server-2014
  • 2 2 respostas
  • 685 Views

2 respostas

  • Voted
  1. Best Answer
    Paul White
    2017-04-07T14:16:11+08:002017-04-07T14:16:11+08:00

    A única dificuldade é decidir como lidar com a(s) etapa(s) do histograma parcialmente coberta (s) pelo intervalo do predicado da consulta. Etapas inteiras do histograma cobertas pelo intervalo de predicados são triviais, conforme observado na pergunta.

    Estimador de cardinalidade herdado

    F= fração (entre 0 e 1) do intervalo de passos coberto pelo predicado da consulta.

    A ideia básica é usar F(interpolação linear) para determinar quantos valores distintos intra-etapa são cobertos pelo predicado. Multiplicar esse resultado pelo número médio de linhas por valor distinto (assumindo uniformidade) e adicionar as linhas iguais de passo fornece a estimativa de cardinalidade:

    Cardinalidade = EQ_ROWS + (AVG_RANGE_ROWS * F * DISTINCT_RANGE_ROWS)
    

    A mesma fórmula é usada para >e >=no CE herdado.

    Novo estimador de cardinalidade

    O novo CE modifica ligeiramente o algoritmo anterior para diferenciar entre >e >=.

    Tomando >primeiro, a fórmula é:

    Cardinalidade = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1)))
    

    Pois >=é:

    Cardinalidade = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))
    

    O + 1reflete que quando a comparação envolve igualdade, uma correspondência é assumida (a suposição de inclusão).

    No exemplo da pergunta, Fpode ser calculado como:

    DECLARE 
        @Q datetime = '1999-10-13T10:48:38.550',
        @K1 datetime = '1999-10-13T10:47:38.550',
        @K2 datetime = '1999-10-13T10:51:19.317';
    
    DECLARE
        @QR float = DATEDIFF(MILLISECOND, @Q, @K2), -- predicate range
        @SR float = DATEDIFF(MILLISECOND, @K1, @K2) -- whole step range
    
    SELECT
        F = @QR / @SR;
    

    O resultado é 0,728219019233034 . Conectando isso na fórmula >=com os outros valores conhecidos:

    Cardinalidade = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))
                = 16 + (16,1956 * ((0,728219019233034 * (409 - 1)) + 1))
                = 16 + (16,1956 * ((0,728219019233034 * 408) + 1))
                = 16 + (16.1956 * (297.113359847077872 + 1))
                = 16 + (16.1956 * 298.113359847077872)
                = 16 +4828.1247307393343837632
                = 4844.1247307393343837632
                = 4844.12473073933 (para precisão flutuante)
    

    Este resultado está de acordo com a estimativa de 4844,13 apresentada na questão.

    A mesma consulta usando o CE herdado (por exemplo, usando o sinalizador de rastreamento 9481) deve produzir uma estimativa de:

    Cardinalidade = EQ_ROWS + (AVG_RANGE_ROWS * F * DISTINCT_RANGE_ROWS)
                = 16 + (16,1956 * 0,728219019233034 * 409)
                = 16 +4823.72307468722
                = 4839.72307468722
    

    Observe que a estimativa seria a mesma para >e >=usando o CE herdado.

    • 14
  2. Doug Lane
    2016-12-31T13:51:38+08:002016-12-31T13:51:38+08:00

    A fórmula para estimar linhas fica um pouco complicada quando o filtro é "maior que" ou "menor que", mas é um número que você pode chegar.

    Os números

    Usando a etapa 193, aqui estão os números relevantes:

    RANGE_ROWS = 6624

    EQ_ROWS = 16

    AVG_RANGE_ROWS = 16.1956

    RANGE_HI_KEY da etapa anterior = 13/10/1999 10:47:38.550

    RANGE_HI_KEY da etapa atual = 13/10/1999 10:51:19.317

    Valor da cláusula WHERE = 13/10/1999 10:48:38.550

    A fórmula

    1) Encontre o ms entre as duas teclas de intervalo hi

    SELECT DATEDIFF (ms, '1999-10-13 10:47:38.550', '1999-10-13 10:51:19.317')

    O resultado é 220767 ms.

    2) Ajuste o número de linhas

    Precisamos encontrar as linhas por milissegundo, mas antes disso, temos que subtrair o AVG_RANGE_ROWS do RANGE_ROWS:

    6624 - 16,1956 = 6607,8044 linhas

    3) Calcule as linhas por ms com o número de linhas ajustado:

    6607,8044 linhas/220767 ms = 0,0299311 linhas por ms

    4) Calcule o ms entre o valor da cláusula WHERE e a etapa atual RANGE_HI_KEY

    SELECT DATEDIFF (ms, '1999-10-13 10:48:38.550', '1999-10-13 10:51:19.317')
    

    Isso nos dá 160767 ms.

    5) Calcule as linhas nesta etapa com base nas linhas por segundo:

    0,0299311 linhas/ms * 160767 ms = 4811,9332 linhas

    6) Lembra como subtraímos o AVG_RANGE_ROWS anteriormente? Hora de adicioná-los de volta. Agora que terminamos de calcular os números relacionados às linhas por segundo, podemos adicionar com segurança o EQ_ROWS também:

    4811.9332 + 16.1956 + 16 = 4844.1288

    Arredondado, essa é a nossa estimativa de 4844,13.

    Testando a fórmula

    Não consegui encontrar nenhum artigo ou postagem de blog sobre por que o AVG_RANGE_ROWS é subtraído antes que as linhas por ms sejam calculadas. Pude confirmar que eles foram contabilizados na estimativa, mas apenas no último milissegundo - literalmente.

    Usando o banco de dados WideWorldImporters , fiz alguns testes incrementais e descobri que a diminuição nas estimativas de linha era linear até o final da etapa, onde 1x AVG_RANGE_ROWS é contabilizado repentinamente.

    Aqui está minha consulta de exemplo:

    SELECT PickingCompletedWhen
    FROM Sales.Orders
    WHERE PickingCompletedWhen >= '2016-05-24 11:00:01.000000'
    

    Atualizei as estatísticas de PickingCompletedWhen e obtive o histograma:

    DBCC SHOW_STATISTICS([sales.orders], '_WA_Sys_0000000E_44CA3770')
    

    Histograma para _WA_Sys_0000000E_44CA3770 (últimas 3 etapas)

    Para ver como as linhas estimadas diminuem conforme nos aproximamos de RANGE_HI_KEY, coletei amostras ao longo da etapa. A diminuição é linear, mas se comporta como se um número de linhas igual ao valor de AVG_RANGE_ROWS simplesmente não fizesse parte da tendência... até que você atinja RANGE_HI_KEY e de repente elas caem como uma dívida não cobrada baixada. Você pode ver isso nos dados de amostra, especialmente no gráfico.

    insira a descrição da imagem aqui

    Observe o declínio constante nas linhas até atingirmos o RANGE_HI_KEY e, em seguida, BOOM, o último bloco AVG_RANGE_ROWS é repentinamente subtraído. Também é fácil identificar em um gráfico.

    insira a descrição da imagem aqui

    Para resumir, o tratamento ímpar de AVG_RANGE_ROWS torna o cálculo das estimativas de linha mais complexo, mas você sempre pode reconciliar o que o CE está fazendo.

    E quanto ao recuo exponencial?

    Exponential Backoff é o método que o novo (a partir do SQL Server 2014) Cardinality Estimator usa para obter melhores estimativas ao usar várias estatísticas de coluna única. Como essa pergunta era sobre uma estatística de coluna única, ela não envolve a fórmula EB.

    • 6

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