Como forçar o SQL a usar hash join com melhor desempenho

Este artigo é compartilhado pela Huawei Cloud Community " [Otimização SQL] Por que às vezes é impossível usar hashjoin com melhor desempenho de execução ", autor: leapdb.

1. Hash join geralmente é melhor do que nestloop join

Normalmente, a complexidade da junção nestloop é O (N quadrado) e a complexidade de tempo da junção hash é O (N), portanto, geralmente tendemos a usar a junção hash.
 
No processo de ajuste de script SQL, geralmente há duas maneiras de forçar o método hash join:

1. Desligue o modo Nestloop no nível da sessão, defina enable_nestloop como desligado;

2. Use o método /*+ hashjoin(ab) */ em SQL para fazer hash das tabelas a e b;
 
CRIAR BANCO DE DADOS test_td COM DBCOMPATIBILITY='td'; 

criar tabela dim_day(day_code char(8)); 
crie a tabela dwr_rpo como selecione data_atual - 1 como day_code; --返回了date类型

test_td=# \d+ dwr_rpo 
                       Tabela "public.dwr_rpo" 
  Coluna | Tipo | Modificadores | Armazenamento | Meta de estatísticas | Descrição 
----------+------+-----------+---------+--------- -+---------------- 
 código_dia | data | | simples | | 
Possui OIDs: não 
Distribuído por: ROUND ROBIN 
Nós de localização: ALL DATANODES 
Opções: orientação=linha, compressão=não 

explicar selecione * 
de dwr_rpo a 
left join dim_day c 
on c.day_code = a.day_code; 

identificação | operação | Linhas eletrônicas | E-distinto | Memória eletrônica | Largura eletrônica | Custos eletrônicos     
---+---------------------------------------------------------- ---+---------+------------+----------+---------+-- ------------ 
 1 | -> Streaming (tipo: GATHER) | 1310148 | | | 1694 | 279235196,70 
 2 | -> Junção à esquerda do loop aninhado (3, 4) | 1310148 | | 1 MB | 1694 | 279229682,933 
 | -> Seq Scan em dwr_rpo a | 1310148 | | 1 MB | 1676 | 46589.164      
 | -> Materializar | 109575 | | 16 MB | 22 | 3747,765       
 | -> Streaming(tipo: BROADCAST) | 109575 | | 2 MB | 22 | 3565,14       
 6 | -> Varredura Seq em dim_day c | 36525 | | 1 MB | 22 | 272.75        

               Informações de predicado (identificadas pelo ID do plano)                 
----------------------------------------- ------------------------------------ 
  2 --Nested Loop Left Join (3, 4) 
        Filtro de junção : ((c.day_code)::timestamp sem fuso horário = a.day_code)

sereia-diagrama-2023-09-06-114052.png

No entanto, o SQL acima não pode obter hash join, independentemente do método usado. Precisamos verificar se os tipos de dados em ambas as extremidades da junção suportam comparação de hash.
 
 
1. Por que às vezes é impossível usar hashjoin com melhor desempenho?

Diferentes tipos de dados têm diferentes funções de cálculo de hash e comparações de hash não podem ser realizadas em tipos de dados mutuamente incompatíveis.

 
2. Por que o hashjoin leva segundos e o nestloop leva duas horas?

Complexidade Nestloop: 131w * 10w = 131 bilhões

Complexidade de hashjoin: 131w

Portanto, há uma grande lacuna de desempenho entre os dois métodos.
 
3. Por que não é possível fazer hash join mesmo que haja conversão de tipo?

Os tipos parecem semelhantes, mas devido às diferenças de precisão, formato, fuso horário, etc. em ambas as extremidades, eles não podem ser considerados diretamente iguais.

4. Quais tipos de dados não suportam hash em junções?
selecione oprname,oprkind,oprcanhash, 
  (selecione typname de pg_type onde oid=oprleft) oprleft, 
  (selecione typname de pg_type onde oid=oprright) oprright 
de pg_operator 
onde oprname='=' e oprcanhash='f'; 

 oprnome | oprkind | oprcanhash | opresquerda | ok     
---------+---------+------------+---------------+ --------------- 
 = | b | f | xid | int8 
 = | b | f | xid32 | int4 
 = | b | f | bom dia | tempo 
 = | b | f | caixa | caixa 
 = | b | f | caminho | caminho 
 = | b | f | intervalo | intervalo 
 = | b | f | dinheiro | dinheiro 
 = | b | f | círculo | círculo 
 = | b | f | lseg | lseg 
 = | b | f | linha | linha 
 = | b | f | pouco | pouco 
 = | b | f | varbit | varbit 
 = | b | f | data | carimbo de data / hora 
 = | b | f | data | carimbo de data / hora 
 = | b | f | carimbo de data/hora | data 
 = | b | f | carimbo de data / hora | data 
 = | b | f | carimbo de data/hora | carimbo de data / hora 
 = | b | f | carimbo de data / hora | carimbo de data / hora 
 = | b | f | vetor ts | vetor 
 = | b | f | consulta | tsquery 
 = | b | f | registro | registro 
 = | b | f | olá | olá 
 = | b | f | hll_hashval | hll_hashval 
 = | b | f | rugindo bitmap | rugido bitmap 
(24 linhas)
 
O principal motivo é que timestamp, timestamptz e date não podem ser hash juntando-se. Outros tipos de dados são menos comuns.
 
Sugestão de desenvolvimento: Os tipos de dados em ambas as extremidades da junção devem ser tão consistentes ou compatíveis entre si quanto possível.
 
5. Por que não há problema com o modo de compatibilidade Oracle, mas há um problema com o modo de compatibilidade td?

current_date é o tipo de data no modo de compatibilidade TD;

current_date é do tipo timestamp no modo de compatibilidade Oracle;

 

Clique para seguir e conhecer as novas tecnologias da Huawei Cloud o mais rápido possível~

O autor da estrutura de código aberto NanUI passou a vender aço e o projeto foi suspenso. A lista gratuita número um na App Store da Apple é o software pornográfico TypeScript. Ele acaba de se tornar popular, por que os grandes começam a abandoná-lo ? Lista TIOBE de outubro: Java tem o maior declínio, C # está se aproximando Java Rust 1.73.0 lançado Um homem foi encorajado por sua namorada AI a assassinar a Rainha da Inglaterra e foi condenado a nove anos de prisão Qt 6.6 lançado oficialmente Reuters: RISC-V a tecnologia se torna a chave para a guerra tecnológica sino-americana Novo campo de batalha RISC-V: não controlada por nenhuma empresa ou país, a Lenovo planeja lançar o Android PC
{{o.nome}}
{{m.nome}}

Acho que você gosta

Origin my.oschina.net/u/4526289/blog/10117402
Recomendado
Clasificación