Ajuste de nível empresarial de desempenho 2023-Hive

Como uma estrutura importante para plataformas de big data, o Hive se tornou uma das estruturas mais usadas para a construção de data warehouses de nível empresarial devido à sua estabilidade e facilidade de uso.

No entanto, se estivermos limitados a usar o Hive sem considerar os problemas de desempenho, será difícil construir um data warehouse perfeito. Portanto, o ajuste de desempenho do Hive é uma habilidade que nossos profissionais de big data devem dominar. Este artigo explicará alguns métodos e técnicas de ajuste de desempenho do Hive.

Como ajustar o desempenho do Hive

Por que se diz que o trabalho de otimização de desempenho é relativamente difícil, porque a otimização de uma tecnologia deve ser um trabalho abrangente, que é uma combinação de várias tecnologias. Se estivermos limitados a apenas uma tecnologia, não poderemos otimizar bem.

A seguir, apresentaremos a diversidade da otimização do Hive de vários ângulos completamente diferentes. Vamos experimentá-la juntos primeiro.

1. Otimização da instrução SQL

Há muitas coisas envolvidas na otimização de instruções SQL. Devido ao espaço limitado, não posso apresentá-las uma a uma. Portanto, usarei alguns exemplos típicos para que todos aprendam esse tipo de pensamento. Se você encontrar problemas de ajuste semelhantes no futuro, você pode se concentrar mais nesses aspectos. Pense nisso.

1. união de todos

insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
from stu_ori
group by s_age

union all

insert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
from stu_ori
group by s_age;

Simplesmente analisamos a instrução SQl acima, ou seja, pegamos os aniversários máximo e mínimo de cada idade e colocamos na mesma tabela. e min. Agrupar o mesmo campo duas vezes na mesma tabela é um grande desperdício. Podemos modificá-lo? Claro que é possível. Deixe-me apresentar uma sintaxe para você: , esta sintaxe será precedida de, e a função é usar um Tabelas podem from ... insert into ... ser inserido várias vezes:

--开启动态分区 
set hive.exec.dynamic.partition=true; 
set hive.exec.dynamic.partition.mode=nonstrict; 

from stu_ori 

insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
group by s_age

insert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
group by s_age;

O SQL acima pode agrupar o campo s_age da tabela stu_ori uma vez e executar duas operações de inserção diferentes.

Este exemplo nos diz que devemos saber mais sobre instruções SQL.Se não conhecermos essa sintaxe, nunca pensaremos dessa maneira .

2. distinto

Vamos ver um SQL primeiro, para remover contagens pesadas:

select count(1) 
from( 
  select s_age 
  from stu 
  group by s_age 
) b;

Este é o número de valores de enumeração para estatísticas simples de idade, por que não usar distinto?

select count(distinct s_age) 
from stu;

Algumas pessoas dizem que usar o primeiro método pode efetivamente evitar a distorção de dados no lado da redução quando a quantidade de dados é particularmente grande, mas é esse o caso?

Independentemente do problema da grande quantidade de dados, o uso de distintivo nos negócios e ambiente atuais será definitivamente mais eficiente do que o método de subconsulta acima . Há várias razões para isso:

  1. O campo a ser deduplicado acima é o campo idade. Você deve saber que o valor de enumeração de idade é muito limitado. Mesmo se a idade entre 1 e 100 anos for calculada, o valor máximo de enumeração de s_age é 100. Se for convertido em MapReduce para explicar Em caso afirmativo, na fase Map, cada Map desduplicará s_age. Como o valor de enumeração s_age é limitado, o s_age obtido por cada Mapa também é limitado, e a quantidade de dados reduzidos finalmente obtidos é o número de mapas * o número de valores de enumeração s_age.

  2. O comando distinto criará uma tabela de hash na memória e a complexidade de tempo de pesquisa e desduplicação é O(1); group by varia muito entre versões diferentes, algumas versões usarão a forma de criar uma tabela de hash para desduplicar e algumas versões usarão By classificação, a complexidade de tempo ideal da classificação não pode atingir O(1). Além disso, a desduplicação do primeiro método (agrupar por) será convertida em duas tarefas, que consumirão mais recursos de E/S de rede de disco.

  3. O mais recente Hive 3.0 adicionou otimização de contagem (distinta).Através da configuração  hive.optimize.countdistinct, mesmo que ocorra distorção de dados, ela pode ser otimizada automaticamente e a lógica da execução do SQL pode ser alterada automaticamente.

  4. O segundo método (distinto) é mais conciso que o primeiro método (agrupar por), e o significado expresso é simples e claro.Se não houver problemas especiais, o código conciso é melhor!

Este exemplo nos diz que às vezes não devemos otimizar demais. O ajuste presta atenção ao ajuste oportuno. O ajuste prematuro pode fazer um trabalho inútil ou até mesmo produzir efeitos negativos. O custo do trabalho e o retorno do ajuste não são diretamente proporcionais. O ajuste precisa seguir certos princípios .

2. Otimização do formato de dados

O Hive fornece uma variedade de formatos de organização de armazenamento de dados, e formatos diferentes terão um grande impacto na eficiência operacional do programa.

Os formatos fornecidos pelo Hive incluem TEXT, SequenceFile, RCFile, ORC e ​​Parquet.

SequenceFile é um arquivo simples com uma estrutura binária de par chave/valor, que foi amplamente usado como um formato de saída/saída MapReduce e como um formato de armazenamento de dados na plataforma Hadoop inicial.

Parquet é um formato de armazenamento de dados colunar compatível com vários mecanismos de computação, como MapRedcue e Spark, e fornece suporte de bom desempenho para estruturas de dados aninhadas em várias camadas. Atualmente, é uma das opções principais para armazenamento de dados no ambiente de produção Hive .um.

A otimização ORC é uma otimização do RCFile, que fornece uma maneira eficiente de armazenar dados do Hive e também pode melhorar o desempenho da leitura, gravação e processamento de dados do Hive e é compatível com vários mecanismos de computação. Na verdade, no ambiente de produção atual, o ORC tornou-se uma das principais opções da Hive para armazenamento de dados.

Usamos os mesmos dados e instrução SQL, mas o formato de armazenamento de dados é diferente e o tempo de execução é o seguinte:

Formato de dados tempo de CPU Tempo de espera do usuário
Arquivo de texto 33 pontos 171 segundos
SequenceFile 38 pontos 162 segundos
Parquet 2 minutos 22 segundos 50 segundos
ORC 1 minuto 52 segundos 56 segundos

Nota: Tempo de CPU: indica o tempo de recursos da CPU do servidor ocupados pelo programa em execução.
Tempo de espera do usuário: registra todo o tempo que o usuário espera desde o envio do trabalho até o retorno do resultado.

A CPU leva 33 minutos para consultar uma tabela de dados do tipo TextFile e 1 minuto e 52 segundos para consultar uma tabela do tipo ORC. O tempo é bastante reduzido. Pode-se ver que diferentes formatos de armazenamento de dados também podem ter uma grande impacto no desempenho do HiveSQL.

3. Muitas otimizações para arquivos pequenos

Se houver muitos arquivos pequenos, para hive, ao consultar, cada arquivo pequeno será considerado um bloco e uma tarefa de mapa será iniciada para ser concluída, e o tempo de início e inicialização de uma tarefa de mapa é muito maior do que o lógico tempo de processamento, portanto, causará muito desperdício de recursos. Além disso, o número de mapas que podem ser executados ao mesmo tempo é limitado.

4. Otimização de Execução Paralela

O Hive converte uma consulta em um ou mais estágios. Esses estágios podem ser o estágio MapReduce, o estágio de amostragem, o estágio de mesclagem e o estágio de limite. Ou outras etapas que podem ser necessárias durante a execução do Hive. Por padrão, o Hive executará apenas um estágio por vez. Porém, um determinado job pode conter muitos estágios, e esses estágios podem não ser totalmente interdependentes, ou seja, alguns estágios podem ser executados em paralelo, o que pode encurtar o tempo de execução de todo o job. Se houver mais estágios que possam ser executados em paralelo, o trabalho poderá terminar mais rapidamente.

Definindo o parâmetro hive.exec.parallel como true, você pode habilitar a execução simultânea. Em um cluster compartilhado, deve-se observar que, se o número de estágios paralelos na tarefa aumentar, a utilização do cluster aumentará.

set hive.exec.parallel=true; //打开任务并行执行
set hive.exec.parallel.thread.number=16; //同一个sql允许最大并行度,默认为8。

Obviamente, há uma vantagem quando os recursos do sistema são relativamente livres, caso contrário, não haverá recursos e o paralelismo não será iniciado.

5. Otimização da distorção de dados

Todos nós conhecemos o princípio da distorção de dados, ou seja, uma determinada chave ou várias chaves ocupam 90% de todos os dados, portanto, a eficiência de toda a tarefa será reduzida pelo processamento dessa chave e também pode causar problemas de memória perda devido à agregação da mesma chave. estouro.

O esquema geral de processamento da distorção de dados do Hive :

Prática comum, por meio do ajuste de parâmetros:

set hive.map.aggr=true;  
set hive.groupby.skewindata = ture;

Quando a opção é definida como true, o plano de consulta gerado possui duas tarefas MapReduce.

No primeiro MapReduce, o conjunto de resultados de saída do mapa é distribuído aleatoriamente entre os redutores e cada redutor realiza operações de agregação parcial e gera os resultados.

O resultado desse processamento é que o mesmo Group By Key pode ser distribuído para diferentes redutores, de forma a atingir o propósito de balanceamento de carga;

A segunda tarefa MapReduce é então distribuída para reduzir de acordo com o Group By Key de acordo com os resultados dos dados pré-processados ​​(esse processo pode garantir que o mesmo Group By Key seja distribuído para o mesmo reduce) e, finalmente, conclui a operação de agregação final.

Mas esta solução é uma caixa preta para nós e não pode ser controlada.

Então, como lidar com esse tipo de distorção de dados no caso de necessidades diárias:

  1. amostragem amostral, cujo conjunto de chaves é obtido;

  2. Adicione números aleatórios às chaves centralizadas de acordo com certas regras;

  3. Realize a junção, porque os dados estão dispersos, portanto, a distorção de dados é evitada;

  4. No resultado do processamento, o número aleatório adicionado anteriormente é dividido em dados originais.

Exemplo: Se for encontrado que 90% das chaves são nulas, uma vez que o volume de dados é muito grande, inevitavelmente ocorrerá distorção de dados. Os seguintes métodos podem ser usados:

SELECT *
FROM a
 LEFT JOIN b ON CASE 
   WHEN a.user_id IS NULL THEN concat('hive_', rand())
   ELSE a.user_id
  END = b.user_id;

Nota : O valor atribuído aleatoriamente ao valor nulo não deve ser igual ao valor existente na tabela, caso contrário o resultado estará errado.

6. Otimização do ajuste do limite limite

Em geral, a instrução Limit ainda precisa executar toda a instrução de consulta e retornar alguns resultados.

Há uma propriedade de configuração que pode ser ativada para evitar isso: sample the data source .

hive.limit.optimize.enable=true -- Ligue a função de amostragem da fonte de dados

hive.limit.row.max.size -- Definir o tamanho mínimo da amostra

hive.limit.optimize.limit.file -- Defina o número máximo de amostras a serem amostradas

Desvantagem : é possível que alguns dados nunca sejam processados

7. Otimização do JOIN

1. Use a mesma chave de conexão

Ao unir 3 ou mais tabelas, se cada cláusula on usar a mesma chave de junção, apenas uma tarefa MapReduce será gerada.

2. Filtre os dados o mais cedo possível

Reduza a quantidade de dados em cada estágio, adicione partições à tabela de partições e selecione apenas os campos que precisam ser usados.

3. Tente fazer operações atômicas

Tente evitar um SQL contendo lógica complexa, você pode usar tabelas intermediárias para completar a lógica complexa.

8. Otimização de empilhamento de predicado

Predicate Pushdown no Hive é a abreviação de predicate pushdown. Em resumo, é tentar reduzir as condições do filtro antes da junção sem afetar os resultados . Depois que o predicado é enviado, as condições de filtro são executadas no lado do mapa, o que reduz a saída do lado do mapa, reduz a quantidade de dados transmitidos no cluster, economiza recursos do cluster e melhora o desempenho da tarefa.

Vejamos a seguinte afirmação:

select s1.key, s2.key 
from s1 left join s2 
on s1.key > '2';

A instrução acima é uma junção à esquerda, s1 é a tabela da esquerda, chamada de tabela de linha reservada, e s2 é a tabela da direita.

P : A condição on é s1.key > '2' executada antes ou depois da junção? Ou seja, o pushdown de predicado será executado?

Resposta : O pushdown de predicado não será executado porque s1 é uma tabela de linha reservada e a condição de filtro será executada após a junção.

E a seguinte afirmação:

select s1.key, s2.key 
from s1 left join s2 
on s2.key > '2';

A tabela s2 não é uma linha reservada, portanto, s2.key>2a condição pode ser enviada para a tabela s2, ou seja, executada antes da junção.

Observe novamente a seguinte frase:

select s1.key, s2.key 
from s1 left join s2 
where s1.key > '2';

A tabela s2 da direita é uma tabela suplementar NULL.

s1 não é uma tabela suplementar NULL, então s1.key>2o pushdown de predicado pode ser executado.

E a seguinte afirmação:

select s1.key, s2.key 
from s1 left join s2 
where s2.key > '2';

Como s2 é uma tabela suplementar NULL, s2.key>2a condição do filtro não pode ser reduzida.

Então, quais são as regras para pushdown de predicado, quando ele será empurrado para baixo e quando não será? A tabela a seguir é resumida e é recomendável salvá-la como uma coleção :

caso :

select a.*  
from a  
left join b on  a.uid = b.uid  
where a.ds='2020-08-10'  
and b.ds='2020-08-10'

O SQL acima cometeu principalmente dois erros :

  1. A condição where da tabela direita (tabela b acima) é gravada após a junção, o que fará com que a tabela inteira seja associada primeiro à partição do filtro.

Nota: Embora a condição where da tabela a também seja escrita após a junção, a tabela a irá empurrar para baixo o predicado, ou seja, a condição where é executada primeiro, e então a junção é executada, mas a tabela b não irá empurrar para baixo o predicado !

  1. A condição on não filtra valores nulos. Se houver um grande número de valores nulos nas duas tabelas de dados, isso causará distorção de dados.

afinal

Princípios de otimização de código:

  • Entenda o princípio da demanda, que é a base da otimização;

  • Segure o princípio do link de dados completo, que é o contexto de otimização;

  • Aderir ao princípio do código conciso, o que facilita a otimização;

  • Falar em otimização quando não há gargalos é pedir problemas.

     

Acho que você gosta

Origin blog.csdn.net/ytp552200ytp/article/details/130419790
Recomendado
Clasificación