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 / 188448
Accepted
GriGrim
GriGrim
Asked: 2017-10-14 12:19:55 +0800 CST2017-10-14 12:19:55 +0800 CST 2017-10-14 12:19:55 +0800 CST

Por que o otimizador escolhe loops aninhados sobre junções de mesclagem aqui?

  • 772

Tenho 3 mesas. #aé uma tabela principal e duas tabelas secundárias, #be #c.

create table #a (a int not null, primary key (a asc)) ;
create table #b (b int not null, primary key (b asc)) ;
create table #c (c int not null, primary key (c asc)) ;

insert into #a (a)
select x*10 + y
from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))x(x)
cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))y(y) ;

insert into #b (b)
select a from #a where a % 5 > 0 ;

insert into #c (c)
select a from #a where a % 4 > 0 ;

Se eu juntar a tabela principal #acom apenas uma tabela secundária, haverá Merge Join no plano de consulta.

select *
from #a a
inner join #b b on a = b ;

insira a descrição da imagem aqui

Mas se eu juntar a tabela principal #acom as duas tabelas secundárias, haverá apenas loops aninhados.

select *
from #a a
inner join #b b on a = b
inner join #c c on a = c ;

insira a descrição da imagem aqui

Por que funciona assim e o que devo fazer para obter duas junções de mesclagem?

Sem inner merge joindica.

sql-server join
  • 3 3 respostas
  • 6062 Views

3 respostas

  • Voted
  1. Best Answer
    Paul White
    2017-10-15T07:35:32+08:002017-10-15T07:35:32+08:00

    Por que funciona assim e o que devo fazer para obter duas junções de mesclagem?

    Com três referências de tabela (o mínimo necessário), a consulta se qualifica para o estágio de Processamento de Transação (também conhecido como pesquisa 0) de otimização baseada em custo.

    Esta etapa é voltada para consultas OLTP, que normalmente se beneficiam de uma estratégia de navegação (baseada em índice). A junção de loops aninhados é o principal tipo de junção física disponível (hash e mesclagem são considerados apenas se nenhum plano de loops aninhado válido puder ser encontrado neste estágio).

    Se este estágio encontrar um plano de baixo custo (bom o suficiente), a otimização baseada em custo para por aí. Isso evita gastar mais tempo em otimização do que podemos esperar economizar em relação à melhor solução encontrada até agora. Se o custo exceder um limite, o otimizador passará para as fases Plano rápido (pesquisa 1), Plano rápido paralelo e Otimização completa (pesquisa 2).

    A consulta com duas referências de tabela não se qualificou para Processamento de Transação e foi direto para o Quick Plan , onde as junções de mesclagem e hash estão disponíveis.

    Veja minha série Deep Dive do Query Optimizer para obter mais informações.

    Sem inner merge joindica.

    Se você absolutamente precisar sugerir um tipo de junção física, prefira fortemente OPTION (MERGE JOIN). Isso permite que o otimizador ainda considere alterar a ordem de junção.

    Dicas de junção como INNER MERGE JOINvem com um implícito OPTION (FORCE ORDER), que limita severamente a liberdade do otimizador, com consequências que a maioria das pessoas (incluindo especialistas) não aprecia.

    • 8
  2. Artashes Khachatryan
    2017-10-14T13:51:48+08:002017-10-14T13:51:48+08:00

    Eu acho que o motivo é porque você não tem dados suficientes em suas tabelas, então o SQL Server não escolhe o plano BEST , ele escolhe o plano Good Enough para executar sua consulta.

    eu tento seguir

    create table #a (a int not null, primary key (a asc))
    create table #b (b int not null, primary key (b asc))
    create table #c (c int not null, primary key (c asc))
    
    insert into #a (a)
    select h+10*g
    from  
    (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))g(g)
    cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))h(h)
    
    
    insert into #b (b)
    select a from #a where a % 5 > 0
    
    insert into #c (c)
    select a from #a where a % 4 > 0
    

    Agora se eu correr

    select *
    from #a a
    inner join #b b on a = b
    inner join #c c on a = c
    

    Aqui está o plano de execuçãoinsira a descrição da imagem aqui

    Se eu usar a dica de junção de mesclagem, recebo o seguinte plano de execução.

    select *
    from #c c
    inner merge join #a a on a = c
    inner merge join #b b on a = b
    

    insira a descrição da imagem aqui

    Portanto, é claro que a junção de mesclagem será melhor neste caso. O custo estimado da subárvore é menor para a consulta com junções de mesclagem, mas ambas as consultas são rápidas o suficiente, ambas fazem apenas 12 leituras lógicas, então o SQL Server decide que a junção NESTED LOOP também é uma boa solução.

    Não vamos adicionar mais dados às nossas tabelas.

    create table #a (a int not null, primary key (a asc))
    create table #b (b int not null, primary key (b asc))
    create table #c (c int not null, primary key (c asc))
    
    insert into #a (a)
    select h+10*g + 100*f + 1000*e+ 10000*z + 100000*y + 1000000*x
    from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))x(x)
    cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))y(y)
    cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))z(z)
    cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))e(e)
    cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))f(f)
    cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))g(g)
    cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))h(h)
    
    
    insert into #b (b)
    select a from #a where a % 5 > 0
    
    insert into #c (c)
    select a from #a where a % 4 > 0
    

    Agora temos 10 milhões de dados em #a, 8 milhões em #b e 6 milhões em #c. Se eu executar a consulta original sem nenhuma dica, recebo junções de mesclagem conforme o esperado.

    select *
    from #a a
    inner join #b b on a = b
    inner join #c c on a = c
    

    insira a descrição da imagem aqui

    Se uma entrada de junção for pequena (menos de 10 linhas) e a outra entrada de junção for bastante grande e indexada em suas colunas de junção, uma junção de loops aninhados de índice será a operação de junção mais rápida porque requer menos E/S e menos comparações.

    Se as duas entradas de junção não forem pequenas, mas forem classificadas em sua coluna de junção (por exemplo, se tiverem sido obtidas por varredura de índices classificados), uma junção de mesclagem será a operação de junção mais rápida.

    As junções de hash podem processar com eficiência entradas grandes, não classificadas e não indexadas.

    Conceitos avançados de ajuste de consulta

    Tipos de junção LOOP, HASH e MERGE

    Noções básicas sobre associações físicas do SQL Server

    • 2
  3. a1ex07
    2017-10-14T13:29:09+08:002017-10-14T13:29:09+08:00

    O otimizador escolhe entre mesclagem/loop aninhado/junção de hash com base nas estatísticas existentes, tamanho das tabelas e presença de índices. Em geral, o loop aninhado é preferível se as entradas forem muito menores que as outras, e ambas estiverem indexadas na coluna de junção, a mesclagem será melhor se o tamanho das duas entradas for bastante igual e indexado. O preenchimento de tabelas envolvidas com mais valores (algumas centenas de milhares de linhas) provavelmente inclinará o otimizador para escolher o algoritmo de junção de mesclagem. Você pode encontrar mais detalhes sobre como ele é implementado no SQLServer aqui .
    Você também pode tentar dicas (digamos FORCE ORDER), mas mesmo que funcione uma vez, não é garantido que sempre gerará o mesmo plano .

    Além disso, tenha em mente que a tarefa do otimizador não é encontrar o melhor plano, mas devolver o plano que é bom o suficiente em tempo hábil.

    • 0

relate perguntas

  • Qual é a diferença entre um INNER JOIN e um OUTER JOIN?

  • 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 é a saída de uma instrução JOIN?

  • 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