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 / 326758
Accepted
SE1986
SE1986
Asked: 2023-05-04 23:40:54 +0800 CST2023-05-04 23:40:54 +0800 CST 2023-05-04 23:40:54 +0800 CST

Como o SQL Server estima a cardinalidade na busca de índice de loops aninhados

  • 772

Estou tentando entender como o SQL Server estima a cardinalidade na consulta de banco de dados Stack Overflow abaixo

Em primeiro lugar, crio o índice

CREATE INDEX IX_PostId ON dbo.Comments
(
    PostId
)
INCLUDE
(
    [Text]
)

E aqui está a consulta:

SELECT  u.DisplayName,
        c.PostId,
        c.Text
FROM    Users u
        JOIN Comments c
            ON u.Reputation = c.PostId
WHERE   u.AccountId = 22547

O plano de execução está aqui

Em primeiro lugar, o SQL Server verifica o índice Clustered na tabela de usuários para retornar os usuários que correspondem ao predicado AccountId. Eu posso ver que ele usa esta estatística:_WA_Sys_0000000E_09DE7BCC

insira a descrição da imagem aqui

Eu posso ver que este usuário não tem uma chave alta de intervalo, então o SQL Server usa as linhas avg_range e estima 1

insira a descrição da imagem aqui

O predicado seek no índice de comentários seek é

insira a descrição da imagem aqui

representa Scalar Operator([StackOverflow2010].[dbo].[Users].[Reputation] as [u].[Reputation]o valor da reputação do(s) usuário(s) na tabela de usuários com o accountId de22547

Eu posso ver três estatísticas carregadas no total:

_WA_Sys_0000000E_09DE7BCC- Users.AccountId (usado para estimar o predicado de busca do índice clusterizado)

IX_PostId- Comments.PostId (usado para estimar o predicado de busca do índice)

_WA_Sys_0000000A_09DE7BCC- Usuários.Reputação (?)

como o servidor SQL apresenta a estimativa na busca do índice? Ele não pode saber a reputação de accountId 22547no tempo de compilação, pois a estatística de ID da conta não mostra isso, portanto, não pode realizar uma pesquisa no histograma para IX_PostId. Eu posso ver que a estatística de reputação também é carregada, então ela usa os dois de alguma forma?

Esta consulta foi executada contra CE 150

sql-server
  • 1 1 respostas
  • 203 Views

1 respostas

  • Voted
  1. Best Answer
    Paul White
    2023-05-16T18:13:50+08:002023-05-16T18:13:50+08:00

    como o servidor SQL apresenta a estimativa na busca do índice? Ele não pode saber a reputação de accountId 22547 no tempo de compilação, pois a estatística de ID da conta não mostra isso, portanto, não pode realizar uma pesquisa no histograma para IX_PostId.

    Nesse caso específico, o SQL Server não deriva uma estimativa de cardinalidade para a busca de índice na tabela Comments porque não precisa . Deixe-me explicar um pouco essa afirmação:

    O processo de compilação sempre envolve uma rodada inicial de estimativa de cardinalidade, onde as estimativas são derivadas com base na forma inicial da representação lógica da consulta após a simplificação. A árvore lógica em seu exemplo é:

    LogOp_Join
        LogOp_Select
        LogOp_Get TBL: dbo.Users(alias TBL: U)
            ScaOp_Comp x_cmpEq
                ScaOp_Identifier [U].AccountId
                ScaOp_Const Value=22547
        LogOp_Get TBL: dbo.Comments(alias TBL: C)
            ScaOp_Comp x_cmpEq
            ScaOp_Identifier QCOL: [C].PostId
            ScaOp_Identifier QCOL: [U].Reputation
    

    Duas estimativas iniciais são necessárias:

    1. Filtro Users.AccountId = 22547 ( LogOp_Select)
    2. Junção interna em Comments.PostId = Users.Reputation ( LogOp_Join)

    Deixando de lado os detalhes desses cálculos por um momento, o fato é que o SQL Server deriva uma seletividade estimada (e cardinalidade) para ambos, de alguma forma. Digamos que a estimativa de cardinalidade após o filtro seja C 1 e a após a junção seja C 2 .

    Durante a otimização baseada em custo posterior, o SQL Server considera diferentes maneiras de implementar a junção. Por exemplo, pode derivar custos estimados para uma junção de mesclagem , junção de hash , junção de loops aninhados ou aplicação (junção de loops correlacionados).

    Quando se trata de considerar um Apply (usando uma regra como JNtoIdxLookup), o otimizador já tem uma estimativa para a entrada superior da junção, C 1 . Também já conhece a cardinalidade do resultado da junção, C 2 . Digamos que C 1 seja 10 e C 2 seja 250 para fins de argumentação.

    Não há necessidade de produzir uma nova estimativa para a entrada inferior do Apply . Sabemos que será executado 10 vezes (uma vez por linha de entrada superior) e a junção produzirá 250 linhas no total. Cada iteração da entrada inferior, portanto, precisa produzir 25 linhas para fazer a soma dos números, 10 * 25 = 250.

    A resposta simples para sua pergunta é que, neste caso , o otimizador não produz uma estimativa de cardinalidade para a busca de índice - ela é derivada diretamente de estimativas de junção e filtro já existentes, por uma regra que considera a implementação de uma junção lógica como um Apply com pesquisa de índice .

    Outros detalhes

    Não há como fugir do fato de que os cálculos de seletividade podem ser extremamente complexos. Eu dei a você uma resposta simples acima porque isso parece responder à sua pergunta. Outros podem querer um pouco mais de detalhes.

    Não posso descrever toda a estrutura de estimativa aqui porque não conheço todos os detalhes e, mesmo que conhecesse, seriam necessários vários livros para cobrir. Dito isso, há algumas coisas que vale a pena dizer e alguns outros recursos para vincular ao leitor interessado.

    AccountId no banco de dados de exemplo Stack Overflow é uma chave não declarada — é exclusiva por usuário. Essas informações devem ser impostas e comunicadas ao otimizador com uma restrição ou índice exclusivo.

    As estatísticas amostradas são úteis para evitar tempos de compilação excessivos, mas podem apresentar uma imagem enganosa. A menos que você esteja procurando entender o mundo altamente envolvido da amostragem estatística, você deve criar ou atualizar as estatísticas com uma varredura completa para obter resultados repetíveis e de alta qualidade.

    O SQL Server tenta transformar subconsultas e aplica-se a junções antes da estimativa inicial. Isso nem sempre é possível, portanto, há ocasiões em que uma estimativa para uma aplicação (possivelmente com uma busca de índice interno) é derivada diretamente. Isso geralmente é modelado como uma série de pesquisas de ponto. Se você reescrever sua consulta para um formulário de aplicação que não pode ser transformado pelo SQL Server em uma junção, obterá estimativas diferentes usando um método diferente. Esta é apenas a natureza da besta.

    SELECT
        U.DisplayName,
        C.PostId,
        C.[Text]
    FROM dbo.Users AS U
    CROSS APPLY
    (
        SELECT
            C1.PostId,
            C1.[Text]
        FROM dbo.Comments AS C1
        WHERE
            C1.PostId = U.Reputation
    ) AS C
    WHERE
        U.AccountId = 22547
    OPTION 
    (
        -- Don't transform the APPLY to a join
        QUERYTRACEON 9114
    );
    

    Derivar estimativas é um processo caro, então o SQL Server procura evitá-lo sempre que possível. Em geral, não há razão específica para favorecer uma estimativa em detrimento de outra. É perfeitamente possível chegar a 'n' estimativas diferentes usando 'n' métodos diferentes (mas igualmente lógicos). Planos de execução complexos às vezes contêm estimativas aparentemente contraditórias porque partes diferentes da árvore usaram abordagens diferentes em momentos diferentes. Novamente, este é o caminho das coisas.

    O SQL Server pode não derivar uma nova estimativa para o lado interno da aplicação em seu exemplo, mas executa alguns cálculos relacionados para estimar o custo da busca do lado interno e quantas vezes ele seria rebobinado ou rebobinado se um carretel fosse introduzido. Cálculos semelhantes são executados ao estimar a economia de custos para uma sugestão de 'índice ausente'.

    Perguntas e respostas relacionadas e leitura adicional (por mim, salvo indicação em contrário):

    • Qual método/fórmula um operador de loops aninhados usa para estimativa de linha?
    • Como o otimizador do SQL Server estima o número de linhas em uma tabela unida?
    • Aplicar problema de estimativa de cardinalidade no SQL Server
    • Internos de estimativa de junção no SQL Server por Dmitry Piliugin
    • Assunção de contenção de junção e variação de modelo CE no SQL Server por Dmitry Piliugin
    • Estimativa de união do SQL Server usando o alinhamento grosso do histograma
    • Estimativa de Cardinalidade: Combinando Estatísticas de Densidade
    • Estimativa de Cardinalidade para um Predicado em uma Expressão COUNT
    • Otimizando seus planos de consulta com o estimador de cardinalidade do SQL Server 2014 por Joseph Sack
    • Estimativa de Cardinalidade para Predicados Múltiplos
    • Estimativa de Cardinalidade para Predicados Disjuntivos (OR) no SQL Server 2014 em diante
    • A suposição de contenção de junção no novo estimador de cardinalidade degrada o desempenho da consulta (Microsoft)
    • 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