SlideShare uma empresa Scribd logo
1 de 59
Hive vs Impala vs Spark
Performance Tuning
Intro
Nesta apresentação serão abordados vários pontos que devem ser tidos em
consideração na arquitectura, configuração e optimização nas plataformas
Hive, Impala e Spark.
Hive MapReduce
Recursos
O ajuste das parametrizações do YARN devem ter
em conta o uso de vCores e memória, configurando
os containers, por forma a usar todos os recursos
disponíveis, além daqueles necessários para
sobrecarga e outros serviços.
Recursos
Configuração de memória do YARN e MapReduce
Deverão ser tido em conta os seguintes valores:
● RAM (quantidade de memória)
● CORES (Número de núcleos de CPU)
● DISKS (número de discos)
A RAM total disponível para o YARN e MapReduce deve considerar a
Memória Reservada.
A memória reservada é a RAM necessária para os processos do
sistema e outros processos do Hadoop (como o HBase).
Memória Reservada = Reserved for stack memory + Reserved for
HBase Memory (se o HBase estiver no mesmo nó).
Para cálculo da Memória Reservada por nó, pode ser usada como
referência a tabela..
Recursos
Parametrização e cálculo YARN e MapReduce
Recursos
Calculo do nº máximo de containers por nó
Nº containers = min (2*CORES, 1.8*DISKS, (Total available RAM) /
MIN_CONTAINER_SIZE).
Calculo Java heap memory do Application Master e Container
O heap memory size deverá ser 80% do tamanho do container, i.e.
do yarn.app.mapreduce.am.resource.mb e
yarn.nodemanager.resource.memory-mb respectivamente.
NOTA: DISKS é referente a dfs.data.dirs (número de discos) por máquina e
MIN_CONTAINER_SIZE é o tamanho mínimo do container (na RAM).
Recursos
Calculo RAM por containers
RAM por container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers).
Exemplo:
Calculo Hive Memory Map Join
hive.auto.convert.join.noconditionaltask.size = 33% do tamanho do container
Recursos
Exemplo de configuração de memória do YARN e MapReduce
Por intermédio de uma ferramenta da Hortonworks é possível
Ter uma base de trabalho das parametrizações:
python hdp-configuration-utils.py -c 4 -m 45 -d 2 -k False
Options:
-c CORES, Number of cores on each host
-m MEMORY, Amount of Memory on each host in GB
-d DISKS, Number of disks on each host
-k HBASE, True if HBase is installed, False is not
Arquitectura dos Dados
A estrutura dos dados é um ponto fulcral na optimização.
Particionamento dos Dados
Conforme imagem, pese embora seja opcional a
estruturação em partições e/ou buckets - tem um
impacto muito positivo na performance final da query
especialmente quando esta tem filtros (Where = ‘XXX’).
Exemplo:
Create Table sale(id in, amount decimal) Partitioned By
(xdate string, state string);
Arquitectura dos Dados
Bucketing
Permite a divisão dos dados (uma partição) em n (ex: 32)
ficheiros por intermédio de uma função de hash sobre a
chave escolhida. Ideal para uma distribuição uniforme dos
dados, tornando os Map-side joins muito mais eficientes
Exemplo:
set hive.enforce.bucketing = true;
Create Table bucketed_table
(Col1 integer, Col2 string, Col3 string, Col4 date, … )
Partitioned By (col4 date)
Clustered By (Col1) INTO 32 BUCKETS
Stored As Parquet TBLPROPERTIES (
parquet.compress'=snappy, 'transactional'='true',
'hive.exec.dynamic.partition'='true',
'hive.exec.dynamic.partition.mode'='nonstrict',
'hive.compactor.initiator.on'='true',
'hive.exec.max.dynamic.partitions.pernode'='150' );
Arquitectura dos Dados
Formato dos Dados
Por questões de transversalidade Hive/Impala formato recomendado é o parquet.
O parquet tem uma compressão eficiente e leitura rápida, um dos pontos que
devem ser tidos em consideração é o tamanho do disk block/row group/file size
no HDFS, que deverá ser entre 512 a 1024 MB.
Exemplo:
ALTER SYSTEM SET `store.parquet.block-size` = 1073741824;
Create Table addresses ( name string, street string, city string, state string, zip int )
STORED AS Parquet tblproperties ("parquet.compress"="snappy");
Caso a ingestão seja feita em formato texto é sempre possível efectuar uma
View sobre os dados já existentes.
Exemplo:
Create Table TABLE_PARQUET STORED AS Parquet AS SELECT * FROM TABLE_CSV;
Arquitectura da Query
A forma como é efectuada a query deverá ser estar o mais
correlacionada possível com a estrutura dos dados.
JOINS
De forma standardizada o JOIN é efectuado conforme imagem.
Cada JOIN deve ser analisado e por intermédio de hints e
parâmetros é possível alterar a forma como o Hive interpreta o
JOIN e a performance destes respectivamente .
Exemplo:
Select /*+ MAPJOIN(c) */ * FROM orders o JOIN cities c ON (o.city_id = c.id);
Arquitectura da Query
JOINS
Com o MAPJOIN permite que a tabela seja carregada para
memória, permitindo que a operação seja feita dentro do
Mapper sem o uso do passo Mapper/Reducer.
Nota: Antes da execução de qualquer query todas as tabelas
envolvidas devem ter as estatísticas actualizadas.
Exemplo:
Tabela:
ANALYZE TABLE <table_name> COMPUTE STATISTICS;
ANALYZE TABLE <table_name> COMPUTE STATISTICS for COLUMNS;
Colunas:
ANALYZE TABLE <table_name> partition (coll="x") COMPUTE STATISTICS for
COLUMNS;
Arquitectura da Query
Escolha - JOIN
Conforme a tabela indica existem prós e contras para cada
tipo de JOIN, como tal a escolha deve ser ponderada de acordo com a realidade de cada query e respectivo modelo.
Arquitectura da Query
Shuffle JOIN
Broadcast JOIN
Sort Merge-Bucket JOIN
Arquitectura da Query
Parametros - JOIN
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions=10000;
set hive.exec.max.dynamic.partitions.pernode=500;
set hive.auto.convert.join.noconditionaltask = true;
set hive.auto.convert.join.noconditionaltask.size = 10000;
set hive.optimize.correlation=true;
set hive.smbjoin.cache.rows=15000;
set hive.auto.convert.join.noconditionaltask.size=20971520;
set hive.mapjoin.localtask.max.memory.usage = 0.999;
set hive.mapjoin.smalltable.filesize = 30000000;
set hive.mapjoin.lazy.hashtable=false;
set hive.exec.parallel=true;
set hive.auto.convert.join = true;
JOIN Tabelas - com Bucketing
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.input.format =
org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
set hive.optimize.bucketmapjoin = true;
Arquitectura da Query
Parametros Genéricos
Vectorization
set hive.vectorized.execution.enabled=true;
set hive.vectorized.execution.reduce.enabled = true;
set hive.exec.dynamic.partition = true;
set hive.exec.dynamic.partition.mode = nonstrict;
set hive.optimize.sort.dynamic.partition=true;
set hive.optimize.reducededuplication=true;
set hive.optimize.index.filter=true;
Cost-Based Optimizer & Statistics
set hive.compute.query.using.stats=true;
set hive.prewarm.enabled=true;
set hive.cbo.enable=true;
set hive.fetch.task.conversion=more;
set hive.fetch.task.conversion.threshold=1073741824;
set hive.stats.autogather=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;
set hive.stats.autographer=true;
Hive on Spark
Recursos
Conforme imagem, conceptualmente o Hive on Spark é mais eficiente que o
MapReduce pois evita os passos intermédios em HDFS e em vez disso usa a
memória. Como tal alguns pontos que devem ser considerados/configurados.
Exemplo:
Recursos
Executors
Por forma não existirem desperdícios de recursos é recomendável que
existam fat executors, i.e. menos executores mas cada um com mais
cores, isto permite uma melhor utilização da memória.
Memory
Para além do tamanho do container deverá ser tido em conta o
tamanho do Driver (spark.driver.memory) e respectivo overhead
(spark.yarn.driver.memoryOverhead) que deverá ser pelo menos 20% do
driver.
Recursos
Para um Use Case de uma VM Cloudera - 37Gb Memória e 4 Cores
Parametros
set hive.execution.engine=spark;
set yarn.nodemanager.resource.cpu-vcores=2;
set yarn.nodemanager.resource.memory-mb=16384;
set yarn.scheduler.maximum-allocation-vcores=4;
set yarn.scheduler.minimum-allocation-mb=4096;
set yarn.scheduler.maximum-allocation-mb=10192;
set spark.executor.memory=1684354560,
set spark.yarn.executor.memoryOverhead=1000;
set spark.driver.memory=10843545604
set spark.yarn.driver.memoryOverhead=800;
set spark.executor.instances=10;
set spark.executor.cores=2;
set hive.spark.dynamic.partition.pruning.map.join.only=true;
set hive.exec.reducers.bytes.per.reducer=6001088640;
Impala
Impala
O Impala é semelhante em alguns aspectos com o Hive, i.e. partilha
os metadados e em parte a sintaxe., porém em vez do MapReduce
usa a memória.
Nota: Algumas funções e tipos de dados não funcionam ou são
diferentes entre o Hive e o Impala.
À semelhança do Hive, no Impala é igualmente importante a
escolha da Arquitectura dos Dados assim como a da própria Query.
Arquitectura dos Dados
A estrutura dos dados é um ponto de partida para a optimização.
Em termos do modelo devem ser tidos em consideração os seguintes aspectos:
● Particionamento
● Sorting
● Runtime filter and dynamic partition pruning
● Tipos de Dados
● Flat vs Nested
Particionamento
Visto que o Impala e o Hive partilham os metadados, a granularidade deve ser bem ponderada. Baixa de mais afeta o
paralelismo e alta de mais irá criar bottlenecks no HDFS NameNode, Hive Metastore e no Impala catalog service.
Arquitectura dos Dados
Sorting
Com a criação da tabela com um Sort inicial, irá funcionar de forma complementar ao particionamento existente pois
pode não só evitar o over-partitioning de uma tabela, assim como torna muito mais eficientes pesquisas de min/max.
Arquitectura dos Dados
Runtime filter e dynamic partition pruning
Por intermédio dos filtros permite optimizar JOINs entre uma tabela
grande e outra que seja pequena (conforme imagem).
Após uma primeira execução alguns parâmetros que devem ser
considerados e testados são:
● RUNTIME_FILTER_MODE
● MAX_NUM_RUNTIME_FILTERS
● DISABLE_ROW_RUNTIME_FILTERING
● RUNTIME_FILTER_MAX_SIZE
● RUNTIME_FILTER_MIN_SIZE
● RUNTIME_BLOOM_FILTER_SIZE
Arquitectura dos Dados
Tipos de Dados
O tipo de dados escolhidos afecta tanto ao
nível da computação da query como do próprio
espaço ocupado no HDFS.
Sempre que possível devem ser escolhidos
tipo de dados numéricos e o formato Parquet.
Nota: Os tipo de de dados CHAR, TIMESTAMP,
TINYINT não são suportados no Impala.
Arquitectura dos Dados
Flat vs Nested
Conforme é possível verificar pela imagem, a
elaboração do modelo de dados tem um grande
impacto na performance. Relações 1-n idealmente
devem ser representadas como nested tables e usar
sempre que possível nested aggregates em vez de
nested data, fazendo com que os JOINs hierárquicos
tenham um custo muito mais baixo.
Exemplo:
Arquitectura da Query
A forma como é efectuada a query deverá ser estar o mais
correlacionada possível com a estrutura dos dados.
JOINS
Por forma a se obter os melhores resultados a nível de
performance devem ser tidos em conta os seguintes pontos:
● JOIN que minimiza o uso dos recursos (Broadcast/Partition).
● Identificar os JOINs que beneficiam de Runtime filters.
● A ordem dos JOINs
Arquitectura da Query
Um dos aspectos mais importantes na execução de uma query
é ser feito à priori, i.e. a computação de todas as estatísticas das
tabelas envolvidas.
Statistics
Por forma a que o Impala consiga fazer a melhor análise das
estatísticas (Explain Plain) é fulcral ter de antemão a
computação das mesmas.
Exemplo:
COMPUTE STATS SALES_PART_2 PARTITION (Region,Country);
COMPUTE INCREMENTAL STATS SALES_PART_2 PARTITION (Region,Country);
Nota: Incremental Stats apenas aplica-se a tabelas particionadas.
Arquitectura da Query
Hints
Os hints são usualmente usados em queries pesadas, quando as estatísticas
não estão devidamente actualizadas ou por outros factores que estejam a
afectar a performance.
Nota: Servem como sugestões e não como directivas. Caso se pretenda forçar
o uso do hint no JOIN deverá ser incluido straight_join no Select.
Hints JOIN
/* +SHUFFLE */ Indica que deve ser usada técnica de particionamento no JOIN.
/* +BROADCAST */ Faz com que o conteúdo do lado direito do JOIN seja
enviado para todos os nós envolvidos no processamento (Default).
Exemplo:
Select straight_join t1.name, t2.id, t3.price from t1 join /* +shuffle */ t2 join /* +broadcast */ t3
on t1.id = t2.id and t2.id = t3.id;
Arquitectura da Query
INSERT/SELECT
/* +SHUFFLE */ Apenas um nó irá escrever, reduzindo a fragmentação, i.e. minimizando o número de ficheiros, assim
como o número de buffers em memória (Default).
/* +NOSHUFFLE */ Desactiva o re-particionamento, o Explain Plan poderá ser mais rápido mas também poderá gerar
muito mais ficheiros com poucos dados.
/* +CLUSTERED */ Ordena os dados, por forma a assegurar que apenas uma partição é escrita por cada nó.
/* +NOCLUSTERED */ Não ordena os dados, recomendável para tabelas Kudu (Default).
HDFS
Por forma a influenciar a forma como o Impala processa os Blocos de Dados do HDFS é possível por intermédio:
* +SCHEDULE_CACHE_LOCAL */, /* +SCHEDULE_DISK_LOCAL */ ou /* +SCHEDULE_REMOTE */. Sendo ainda possível
combinar com a hint /* +RANDOM_REPLICA */ que activa um desempate random na escolha dos blocos HDFS.
Exemplo:
Select * /* +SCHEDULE_CACHE_LOCAL,RANDOM_REPLICA */ from table;
Arquitectura da Query
HDFS Caching
Com o caching de dados em memória permite que o Impala leia a
informação directamente da memória evitando leituras ao HDFS, trazendo
alguns improvements na performance (Conforme imagem).
O caching pode ser feito de uma tabela inteira ou apenas de uma partição,
sendo ainda possível indicar o nº de hosts (replication = x).
Nota: Esta técnica não é aplicável a tabelas HBase, S3, Kudu, ou Isilon.
Exemplo:
HDFS
hdfs cacheadmin -addPool pool_1 -owner impala -limit 4000000000
IMPALA
alter table SALES_PART partition (year=1960) set cached in 'pool_1' ;
alter table SALES_PART set cached in 'pool_1' with replication = 3;
Arquitectura da Query
Parametros Genéricos
set mem_limit=13221225472;
set query_timeout_s = 1000;
set optimize_partition_key_scans = true;
set exec_single_node_rows_threshold = 20000;
set default_join_distribution_mode = 1;
set max_num_runtime_filters = 100;
set rm_initial_mem = 1000000;
set runtime_filter_wait_time_ms = 600;
set strict_mode = true;
set disable_row_runtime_filtering = true;
set sync_ddl = true;
set batch_size=1000;
set num_nodes = '';
set max_scan_range_length=0;
set num_scanner_threads = 0;
Spark
Recursos
Conceptualmente a configuração dos recursos no Spark são semelhantes ao que foi dito na
secção do Hive on Spark. Porém é necessário ressalvar que caso seja configurado um executor
de 10Gb o Spark irá criar uma JVM conforme imagem, i.e. por forma a prevenir erros de falta
memória (00Ms) apenas 90% é configurável (“Safety” - spark.storage.safetyFraction).
Posteriormente temos efectivamente “Storage” - spark.storage.memoryFraction e “Shuffle” -
spark.shuffle.memoryFraction, que por default são respectivamente 60% e 20%. Concluindo
dos iniciais 10Gb, temos apenas 5.4Gb (JVM*90%*60%).
Internamente existe outra configuração “shuffle” - spark.shuffle.safetyFraction que é 80% da
JVM Heap, i.e. 80%*20% - 1.6Gb. Esta área de memória é usada para agregações pré-reduce
(reduceByKey), caso os resultados não caibam nesta área o Spark irá escrever no HDFS.
A nível dos parâmetros de uma JVM que devem ser também considerados, especialmente se
esta tiver menos de 32Gb é a flag -XX:+UseCompressedOops pois em termos de optimização
faz com que os apontadores passem a ser de 4 Bytes ao invés de 8 Bytes (Default).
Recursos
Memória
No Spark o uso da memória pode de uma forma grosseira ser dividido em três blocos:
● Caching (.cache ou .persist)
● Shuffle (buffering de dados entre nós)
● Tasks (.map)
E para cada situação os parâmetros podem e devem ser ajustados.
Exemplo:
Low cluster memory
sparkConf.set("spark.storage.memoryFraction", "0.1")
sparkConf.set("spark.shuffle.memoryFraction", "0.2")
Shuffle intensive jobs
sparkConf.set("spark.storage.memoryFraction", "0.1")
sparkConf.set("spark.shuffle.memoryFraction", "0.8")
Computation intensive jobs
sparkConf.set("spark.storage.memoryFraction", "0.1")
sparkConf.set("spark.shuffle.memoryFraction", "0.6")
Recursos
Caching
No Spark é fulcral evitar a escrita no HDFS, para tal o recomendável é o caching data e
conforme imagem existem diversas técnicas e com diversos resultados:
● MEMORY_ONLY - Dados como objectos Java. Em termos de espaço é pouco
eficiente mas é o mais rápido.
● MEMORY_ONLY_SER - Dados serializados, porém existe o custo CPU (serialized/deserialized).
● MEMORY_AND_DISK_SER - Dados serializados, porém tudo o que não caiba em memória será
escrito no HDFS. Uma boa opção caso exista alto processamento envolvido ou joins/reduces
antes de caching.
● DISK_ONLY - Dados em HDFS.
Nota: Por default o serializer é em Java, sendo recomendável o Kryo Serializer
Exemplo:
rdd.cache() ou rdd.persist(storageLevel.MEMORY_ONLY).
sparkConf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
sparkConf.set("spark.storage.memoryFraction", "0.6")
sparkConf.set("spark.shuffle.memoryFraction", "0.2")
Recursos
GC
À medida que um Job Spark é executado e existe a persistência de objectos em
caching que irá conduzir a um aumento do consumo de memória e por sua vez
despoleta mais tentativas de GC, nestas situações recomenda-se que sejam
libertados todos e quaisquer RDD’s que já não estejam a ser usados.
Um dos factores que também influencia a eficiência do GC é a técnica usada:
● Serial GC (-XX:+UseSerialGC)
● Parallel GC (-XX:+UseParallelGC)
● Parallel Old GC (-XX:+UseParallelOldGC)
● Concurrent Mark Sweep (CMS) Collector (-XX:+UseConcMarkSweepGC)
● G1 Garbage Collector (-XX:+UseG1GC)
Sendo o recomendado o G1, pois é o que lida melhor com a flutuação dos heap
sizes e apresenta melhor taxa de transferência e baixa latência.
Exemplo:
sparkConf.set("spark.executor.extraJavaOptions", "-XX:+UseG1GC")
Arquitectura
Particionamento e Paralelismo
No processamento é recomendável a configuração de 2-3 tasks por CPU core. Os RDD’s são
tipicamente particionados com base no número de blocos HDFS ocupados. Por intermédio
dos mecanismos de particionamento permite reduzir o número de shuffles, sendo estes:
● Hash partitioning - As keys que têm o mesmo hash estão no mesmo nó.
● Range partitioning - As keys que se encontram dentro do mesmo range estão no mesmo nó.
Pouco particionamento faz com que não seja dado o uso correcto ao paralelismo(Data
skewing e/ou Less concurrency), já em excesso faz com que as tasks demorem mais do que
é suposto (Task scheduling). Usualmente o número ronda entre 2x o número de cores no
Cluster e 100k partições. Com o correcto particionamento tem igualmente um impacto muito
positivo em operações de shuffling data (cogroup(), groupWith(), join(), groupByKey(),
combineByKey(), reduceByKey(), and lookup()).
Arquitectura
Particionamento e Paralelismo
É necessário conhecer bem o Job que estamos a correr. Conforme imagem, por default
os valores dos parâmetros spark.default.parallelism=12 e
spark.sql.shuffle.partitions=200, para o cálculo adequado destes parâmetros é
necessário identificar na timeline do Job se existem tasks com bastante scheduler delay
deverá ser reduzido o shuffle partition.
Nº Partições = Total input dataset size / partition size
Nível de Localidade
A localidade dos dados e respectivo processamento tem um impacto directo
na performance do Job, quanto mais próximos (Dados/Processamento) melhor.
● PROCESS_LOCAL - Execução no mesmo processo que a fonte de dados.
● NODE_LOCAL - Execução no nó da fonte de dados.
● RACK_LOCAL - Execução no rack da fonte de dados.
● ANY - Em qualquer sítio na rede.
Em algumas situações (streaming) poderá ser necessário um ajuste do delay do
cálculo da localidade, i.e. através do parâmetro spark.locality.wait, que por default é
de 3s e poderá ser ajustado para 0-0.5.
Arquitectura
Acções/Transformações
As acções/transformações é uma das fases no Spark que requerem
especial atenção. Sempre que possível devem ser usadas
transformações Narrow (ex: map() e filter()) em invez das Wide, pois
conforme se observa na imagem operações como groupByKey(),
reduceByKey() e join() implicam múltiplas partições e shuffling.
Caso sejam necessárias transformações Wide podem ser feitas
algumas optimizações, tais como por exemplo:
● No Join() por forma a minimizar o shuffling deve ser feito broadcasting o
grupo de dados mais pequeno ou hash partitioning de ambos os RDD pelas
respectivas chaves.
● Redução associativa deve ser usado reduceByKey() e evitar groupByKey().
● Junção de dois datasets agrupados e mantém-los agrupados deve ser
usado o cogroup() ao invés do flatMap-join-groupBy().
● Re-particionamento de dados deverá ser feito com
repartitionAndSortWithinPartitions() ao invés de se feio separadamente o re-
particionamento e posteriormente o sort a cada partição pois fará com que
exista comparativamente mais operações de shuffling.
Arquitectura
Dataset/Dataframe
Para Jobs que operem com instruções SQL, Dataframes/Datasets é o
caminho a escolher, pois a API contém muitas optimizações por forma a
que estas estruturas operem de forma semelhante a uma tabela do
modelo relacional (ex: Tabelas Hive, HDFS, etc...).
O dataframe porém apresenta algumas limitações que devem ser tidas
em consideração:
● A API do SparkSQL não permite a compilação time type safety.
● Após a transformação de um RDD em DF não é possível a sua regressão.
Exemplo:
Arquitectura
Sorting
Tendo como objectivo final a escrita de queries SQL com JOIN’s no SparkSQL
pode ser benéfico fazer o sort à prior aos dados nos dataframes
Exemplo:
Distribute By
SET spark.sql.shuffle.partitions = 2
df.repartition($"key", 2)
Cluster By (Distribute By + Sort By)
SET spark.sql.shuffle.partitions = 2
df .repartition($"key", 2).sortWithinPartitions()
Broadcasting Variables
Tendo em consideração a arquitectura e a localização dos dados deverá ser
considerada a possibilidade da distribuição das variáveis pelos diversos nós,
por exemplo dados de referência.
Exemplo
val b = sc.broadcast(1); b: org.apache.spark.broadcast.Broadcast[Int] = Broadcast(0)
Sort By
df.sortWithinPartitions()
Skewed Data
SET spark.sql.shuffle.partitions = 5
SELECT * FROM df DISTRIBUTE BY key, value
SQL
HiveContext
No Spark mais concretamente com a API HiveContext é possível aceder aos
metadados em Hive e assim como proceder a algumas optimizações à
semelhança do que foi feito no Hive on Spark.
Exemplo:
hiveCtx = HiveContext(sc)
hiveCtx.sql("SET yarn.nodemanager.resource.cpu-vcores=4")
hiveCtx.sql("SET yarn.nodemanager.resource.memory-mb=16384")
hiveCtx.sql("SET yarn.scheduler.maximum-allocation-vcores=4")
hiveCtx.sql("SET yarn.scheduler.minimum-allocation-mb=4096")
hiveCtx.sql("SET yarn.scheduler.maximum-allocation-mb=8192")
SQL
JOINS
Usualmente são a grande fonte de problemas de performance:
● Shuffle Hash
● Broadcast Hash
● Skew (Data skew)
● Cartesian
● One to Many
● Theta
Shuffle Hash é usado quando existe uma distribuição uniforme das
chaves e assim como o paralelismo usado. Quando não é o caso
conforme imagem, uma possível solução pode passar para Broadcast se
um dos dataframes couber em memória ou por sua vez filtrar os dados.
Broadcast Hash é maior parte das vezes melhor que o Shuffle Hash, para
tal deve-se validar no Explain Plan se o Spark está a usá-lo, uma
optimização que pode e deve ser feita é o caching do dataframe mais
pequeno.
SQL
JOINS
Skew é usado quando existe data skew , i.e. uma distribuição não-
uniforme das partições, que num JOIN implica shuffling e é mau para a
performance. É possível melhorar esta situação por intermédio de hints
por forma a que o Spark construa uma explain plan melhor.
Exemplo:
Tabela com Skew
Select /*+ SKEW('orders') */ * From orders, customers Where c_custId = o_custId
Tabela com Skew - Apenas às colunas do JOIN
Select /*+ SKEW('orders', ('o_custId', 'o_storeRegionId')) */ * From orders, customers
Where o_custId = c_custId And o_storeRegionId = c_regionId
Cartesian é muitas vezes um problema camuflado, pois em termos de
output, conforme imagem é algo que pode implodir rapidamente. Um
possível workaround a esta situação é:
● Criação de um RDD com os UID por UID.
● Forçar o Broadcast às linhas da tabela.
● Executar uma UDF dado o UID por UID que procura na tabela e
efectua o respectivo processamento.
SQL
JOINS
One to Many Join à semelhança do produto cartesiano também
pode implodir no número de resultados, pelo que deixa de ser um
problema desde que seja usado parquet nas tabelas.
Theta Join é um JOIN peculiar que implica um conjunto de loops
por forma a validar a condição na cláusula ON. Uma forma de
optimizar é a criação de buckets para o matching da condição ON.
Exemplo:
ON(Car_Price >= Boat_Price)
ON(KeyA < KeyB + 1000)
SQL
Bucketing
Conforme mencionado no Theta Join e na secção Hive - Arquitectura
de Dados, bucketing é uma solução elegante para JOIN’s, i.e. por
exemplo chaves que são usadas em vários JOIN’s (ID’s, etc…) i.e.:
Bucketing = pre (Shuffle + Sort) nas Chaves dos JOIN’s
Porém, conforme imagens o bucketing do Spark é conceptualmente
diferente e não é compatível com o do Hive.
Em termos de performance é expectável obter ganhos 2x a 5x após
bucketing.
Exemplo:
set spark.sql.sources.bucketing.enabled = true
Dataframe API
df.write.bucketBy(numBuckets,”col1”,...).sortBy(“col1”,...).saveAsTable(“bucketed_Table”
)
SQL Statement
Create Table bucketed_table(col1 int, …) using Parquet
Clustered By (col1, …) Sorted By (col1, …) Into X Buckets
SQL
Parametros Genéricos
hiveCtx = HiveContext(sc)
hiveCtx.sql("set spark.executor.memory=1638454560")
hiveCtx.sql("set spark.yarn.executor.memoryOverhead=1000")
hiveCtx.sql("set spark.driver.memory=10843545604")
hiveCtx.sql("set spark.yarn.driver.memoryOverhead=1000")
hiveCtx.sql("set spark.executor.instances=12")
hiveCtx.sql("set spark.executor.cores=4")
hiveCtx.sql("set spark.sql.shuffle.partitions = 1")
hiveCtx.sql("set spark.default.parallelism = 12")
hiveCtx.sql("set spark.locality.wait = 0")
hiveCtx.sql("set spark.sql.autoBroadcastJoinThreshold=1048576000")
hiveCtx.sql("set spark.serialize = org.apache.spark.serializer.KryoSerializer")
hiveCtx.sql("set spark.storage.memoryFraction = 0.6")
hiveCtx.sql("set spark.shuffle.memoryFraction = 0.3")
hiveCtx.sql("set spark.executor.extraJavaOptions = -XX:+UseG1GC")
Aqui é demonstrado as grandes vantagens da execução de um job em Spark
e/ou em memória vs tradicional MapReduce
Resumo
● Escolher as Arquitecturas correctas
● Recursos Disponíveis vs Necessários
● Evitar Shuffling Data e GC
Conclusão
Tune the job not the Cluster!
Bibliografia
HIVE - MapReduce
https://www.cloudera.com/documentation/enterprise/5-10-
x/topics/cdh_ig_yarn_tuning.html
https://hortonworks.com/blog/how-to-plan-and-configure-yarn-in-hdp-2-0/
https://www.justanalytics.com/blog/apache-hive-memory-management-tuning
https://raw.githubusercontent.com/hortonworks/hdp-configuration-
utils/master/2.1/hdp-configuration-utils.py
https://hortonworks.com/blog/managing-cpu-resources-in-your-hadoop-yarn-
clusters/
https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-
2.4.0/bk_performance_tuning/content/hive_perf_best_pract_design_data_stg_s
martly.html
https://streever.atlassian.net/wiki/spaces/HADOOP/pages/1933314/Hive+Perf
ormance+Tips
https://data-flair.training/blogs/bucketing-in-hive/
Bibliografia
HIVE on Spark
https://www.quora.com/What-is-the-difference-in-idea-design-and-code-
between-Apache-Spark-and-Apache-Hadoop
https://www.slideshare.net/ye.mikez/hive-tuning
https://www.qubole.com/blog/hive-best-practices/
https://www.reddit.com/r/hadoop/comments/3iglwh/tuning_yarn_memory_for
_your_cluster/
https://rea.tech/how-we-optimize-apache-spark-apps/
https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-
2.4.0/bk_performance_tuning/content/ch_hive_hi_perf_best_practices.html
https://www.cloudera.com/documentation/enterprise/5-14-
x/topics/admin_hos_oview.html
https://www.justanalytics.com/blog/apache-hive-memory-management-tuning
Bibliografia
Impala
https://cdn.oreillystatic.com/en/assets/1/event/193/Tuning%20Impala_%20Th
e%20top%20five%20performance%20optimizations%20for%20the%20best%20B
I%20and%20SQL%20analytics%20on%20Hadoop%20Presentation.pdf
https://www.slideshare.net/cloudera/performance-of-apache-impala
https://www.cloudera.com/documentation/enterprise/5-8-
x/topics/impala_perf_hdfs_caching.html
https://www.cloudera.com/documentation/enterprise/5-11-
x/topics/impala_hints.html#hints
http://www.clouderaworldtokyo.com/session-download/B3-Kudu-2FImpala-
Strata-talk.pdf
https://www.slideshare.net/Hadoop_Summit/inmemory-caching-in-hdfs-lower-
latency-same-great-taste-33921794
http://fdahms.com/2015/10/04/writing-efficient-spark-jobs/
https://www.dremio.com/tuning-parquet/
Bibliografia
Spark
https://community.hortonworks.com/articles/42803/spark-on-yarn-executor-
resource-allocation-optimiz.html
https://www.slideshare.net/databricks/optimizing-apache-spark-sql-joins
https://zerogravitylabs.ca/spark-performance-tuning-checklist/
http://fdahms.com/2015/10/04/writing-efficient-spark-jobs/
https://www.quora.com/What-is-the-difference-between-RDD-Dataset-and-
DataFrame-in-Spark
https://github.com/vaquarkhan/vk-wiki-notes/wiki/Apache-Spark-Join-
guidelines-and-Performance-tuning
https://deepsense.ai/optimize-spark-with-distribute-by-and-cluster-by/
https://docs.databricks.com/spark/latest/spark-sql/skew-join.html
https://www.slideshare.net/TejasPatil1/hive-bucketing-in-apache-spark
https://dzone.com/articles/apache-spark-performance-tuning-degree-of-parallel
Obrigado
Big Data Engineer
Tiago Simões

Mais conteúdo relacionado

Mais procurados

In-memory Caching in HDFS: Lower Latency, Same Great Taste
In-memory Caching in HDFS: Lower Latency, Same Great TasteIn-memory Caching in HDFS: Lower Latency, Same Great Taste
In-memory Caching in HDFS: Lower Latency, Same Great TasteDataWorks Summit
 
Geospatial Options in Apache Spark
Geospatial Options in Apache SparkGeospatial Options in Apache Spark
Geospatial Options in Apache SparkDatabricks
 
Scylla Compaction Strategies
Scylla Compaction StrategiesScylla Compaction Strategies
Scylla Compaction StrategiesNadav Har'El
 
11. Storage and File Structure in DBMS
11. Storage and File Structure in DBMS11. Storage and File Structure in DBMS
11. Storage and File Structure in DBMSkoolkampus
 
Master Data Management (MDM) con Talend
Master Data Management (MDM) con TalendMaster Data Management (MDM) con Talend
Master Data Management (MDM) con TalendStratebi
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDBKnoldus Inc.
 
Designing and Building Next Generation Data Pipelines at Scale with Structure...
Designing and Building Next Generation Data Pipelines at Scale with Structure...Designing and Building Next Generation Data Pipelines at Scale with Structure...
Designing and Building Next Generation Data Pipelines at Scale with Structure...Databricks
 
Zeus: Uber’s Highly Scalable and Distributed Shuffle as a Service
Zeus: Uber’s Highly Scalable and Distributed Shuffle as a ServiceZeus: Uber’s Highly Scalable and Distributed Shuffle as a Service
Zeus: Uber’s Highly Scalable and Distributed Shuffle as a ServiceDatabricks
 
Apache Arrow: High Performance Columnar Data Framework
Apache Arrow: High Performance Columnar Data FrameworkApache Arrow: High Performance Columnar Data Framework
Apache Arrow: High Performance Columnar Data FrameworkWes McKinney
 
Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...
Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...
Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...Hortonworks
 
¿Qué es el gobierno de los datos?
¿Qué es el gobierno de los datos? ¿Qué es el gobierno de los datos?
¿Qué es el gobierno de los datos? www.cathedratic.com
 
Performance Troubleshooting Using Apache Spark Metrics
Performance Troubleshooting Using Apache Spark MetricsPerformance Troubleshooting Using Apache Spark Metrics
Performance Troubleshooting Using Apache Spark MetricsDatabricks
 
Introduction to MongoDB.pptx
Introduction to MongoDB.pptxIntroduction to MongoDB.pptx
Introduction to MongoDB.pptxSurya937648
 
Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...
Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...
Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...Edureka!
 
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin Huai
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin HuaiA Deep Dive into Spark SQL's Catalyst Optimizer with Yin Huai
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin HuaiDatabricks
 
Developing and Implementing Scorecards and Dashboards
Developing and Implementing Scorecards and DashboardsDeveloping and Implementing Scorecards and Dashboards
Developing and Implementing Scorecards and DashboardsVictor Holman
 
Apache Superset - open source data exploration and visualization (Conclusion ...
Apache Superset - open source data exploration and visualization (Conclusion ...Apache Superset - open source data exploration and visualization (Conclusion ...
Apache Superset - open source data exploration and visualization (Conclusion ...Lucas Jellema
 

Mais procurados (20)

In-memory Caching in HDFS: Lower Latency, Same Great Taste
In-memory Caching in HDFS: Lower Latency, Same Great TasteIn-memory Caching in HDFS: Lower Latency, Same Great Taste
In-memory Caching in HDFS: Lower Latency, Same Great Taste
 
Data science
Data scienceData science
Data science
 
Geospatial Options in Apache Spark
Geospatial Options in Apache SparkGeospatial Options in Apache Spark
Geospatial Options in Apache Spark
 
Scylla Compaction Strategies
Scylla Compaction StrategiesScylla Compaction Strategies
Scylla Compaction Strategies
 
11. Storage and File Structure in DBMS
11. Storage and File Structure in DBMS11. Storage and File Structure in DBMS
11. Storage and File Structure in DBMS
 
Master Data Management (MDM) con Talend
Master Data Management (MDM) con TalendMaster Data Management (MDM) con Talend
Master Data Management (MDM) con Talend
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
 
Object oriented databases
Object oriented databasesObject oriented databases
Object oriented databases
 
Designing and Building Next Generation Data Pipelines at Scale with Structure...
Designing and Building Next Generation Data Pipelines at Scale with Structure...Designing and Building Next Generation Data Pipelines at Scale with Structure...
Designing and Building Next Generation Data Pipelines at Scale with Structure...
 
Zeus: Uber’s Highly Scalable and Distributed Shuffle as a Service
Zeus: Uber’s Highly Scalable and Distributed Shuffle as a ServiceZeus: Uber’s Highly Scalable and Distributed Shuffle as a Service
Zeus: Uber’s Highly Scalable and Distributed Shuffle as a Service
 
Apache Arrow: High Performance Columnar Data Framework
Apache Arrow: High Performance Columnar Data FrameworkApache Arrow: High Performance Columnar Data Framework
Apache Arrow: High Performance Columnar Data Framework
 
Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...
Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...
Modern Data Architecture for a Data Lake with Informatica and Hortonworks Dat...
 
¿Qué es el gobierno de los datos?
¿Qué es el gobierno de los datos? ¿Qué es el gobierno de los datos?
¿Qué es el gobierno de los datos?
 
Spark Workshop
Spark WorkshopSpark Workshop
Spark Workshop
 
Performance Troubleshooting Using Apache Spark Metrics
Performance Troubleshooting Using Apache Spark MetricsPerformance Troubleshooting Using Apache Spark Metrics
Performance Troubleshooting Using Apache Spark Metrics
 
Introduction to MongoDB.pptx
Introduction to MongoDB.pptxIntroduction to MongoDB.pptx
Introduction to MongoDB.pptx
 
Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...
Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...
Apache Spark Tutorial | Spark Tutorial for Beginners | Apache Spark Training ...
 
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin Huai
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin HuaiA Deep Dive into Spark SQL's Catalyst Optimizer with Yin Huai
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin Huai
 
Developing and Implementing Scorecards and Dashboards
Developing and Implementing Scorecards and DashboardsDeveloping and Implementing Scorecards and Dashboards
Developing and Implementing Scorecards and Dashboards
 
Apache Superset - open source data exploration and visualization (Conclusion ...
Apache Superset - open source data exploration and visualization (Conclusion ...Apache Superset - open source data exploration and visualization (Conclusion ...
Apache Superset - open source data exploration and visualization (Conclusion ...
 

Semelhante a Hive vs impala vs spark - tuning

Hadoop - Mãos à massa! Qcon2014
Hadoop - Mãos à massa! Qcon2014Hadoop - Mãos à massa! Qcon2014
Hadoop - Mãos à massa! Qcon2014Thiago Santiago
 
Path to the future #5 - Melhores práticas de data warehouse no Amazon Redshift
Path to the future #5 - Melhores práticas de data warehouse no Amazon RedshiftPath to the future #5 - Melhores práticas de data warehouse no Amazon Redshift
Path to the future #5 - Melhores práticas de data warehouse no Amazon RedshiftAmazon Web Services LATAM
 
Modelos de computação distribuída no Hadoop
Modelos de computação distribuída no HadoopModelos de computação distribuída no Hadoop
Modelos de computação distribuída no HadoopBig Data Week São Paulo
 
Filesystem distribuído com hadoop!!!
Filesystem distribuído com hadoop!!! Filesystem distribuído com hadoop!!!
Filesystem distribuído com hadoop!!! Alessandro Binhara
 
Dsi 015 - poo e php - conexão com bancos de dados usando pdo
Dsi   015 - poo e php - conexão com bancos de dados usando pdoDsi   015 - poo e php - conexão com bancos de dados usando pdo
Dsi 015 - poo e php - conexão com bancos de dados usando pdoJorge Luís Gregório
 
[DTC21] André Marques - Jornada do Engenheiro de Dados
[DTC21] André Marques - Jornada do Engenheiro de Dados[DTC21] André Marques - Jornada do Engenheiro de Dados
[DTC21] André Marques - Jornada do Engenheiro de DadosDeep Tech Brasil
 
PHPMyadmin - Introdução
PHPMyadmin - IntroduçãoPHPMyadmin - Introdução
PHPMyadmin - IntroduçãoMarco Pinheiro
 
hibernate annotation
hibernate annotationhibernate annotation
hibernate annotationeduardo dias
 
Mongo Db - PHP Day Workshop
Mongo Db - PHP Day WorkshopMongo Db - PHP Day Workshop
Mongo Db - PHP Day WorkshopDiego Sana
 
Design Patterns para Tuning Pentaho com Ctools
Design Patterns para Tuning Pentaho com CtoolsDesign Patterns para Tuning Pentaho com Ctools
Design Patterns para Tuning Pentaho com Ctoolse-Setorial
 
PostgreSQL-Prático.pdf
PostgreSQL-Prático.pdfPostgreSQL-Prático.pdf
PostgreSQL-Prático.pdfArleiEvaristo
 
Amostra Resolucao da Prova Sefaz 2007 Prof Jaime
Amostra   Resolucao da Prova Sefaz 2007   Prof JaimeAmostra   Resolucao da Prova Sefaz 2007   Prof Jaime
Amostra Resolucao da Prova Sefaz 2007 Prof JaimeWalter Cunha
 

Semelhante a Hive vs impala vs spark - tuning (20)

Hadoop - Mãos à massa! Qcon2014
Hadoop - Mãos à massa! Qcon2014Hadoop - Mãos à massa! Qcon2014
Hadoop - Mãos à massa! Qcon2014
 
Introdução ao Hive
Introdução ao HiveIntrodução ao Hive
Introdução ao Hive
 
No sql std
No sql stdNo sql std
No sql std
 
Path to the future #5 - Melhores práticas de data warehouse no Amazon Redshift
Path to the future #5 - Melhores práticas de data warehouse no Amazon RedshiftPath to the future #5 - Melhores práticas de data warehouse no Amazon Redshift
Path to the future #5 - Melhores práticas de data warehouse no Amazon Redshift
 
Amazon Redshift
Amazon RedshiftAmazon Redshift
Amazon Redshift
 
Seminário Hadoop
Seminário HadoopSeminário Hadoop
Seminário Hadoop
 
Modelos de computação distribuída no Hadoop
Modelos de computação distribuída no HadoopModelos de computação distribuída no Hadoop
Modelos de computação distribuída no Hadoop
 
Filesystem distribuído com hadoop!!!
Filesystem distribuído com hadoop!!! Filesystem distribuído com hadoop!!!
Filesystem distribuído com hadoop!!!
 
Dsi 015 - poo e php - conexão com bancos de dados usando pdo
Dsi   015 - poo e php - conexão com bancos de dados usando pdoDsi   015 - poo e php - conexão com bancos de dados usando pdo
Dsi 015 - poo e php - conexão com bancos de dados usando pdo
 
[DTC21] André Marques - Jornada do Engenheiro de Dados
[DTC21] André Marques - Jornada do Engenheiro de Dados[DTC21] André Marques - Jornada do Engenheiro de Dados
[DTC21] André Marques - Jornada do Engenheiro de Dados
 
C-Store 7 years later
C-Store 7 years laterC-Store 7 years later
C-Store 7 years later
 
PHPMyadmin - Introdução
PHPMyadmin - IntroduçãoPHPMyadmin - Introdução
PHPMyadmin - Introdução
 
Qcon Rio 2015 - Data Lakes Workshop
Qcon Rio 2015 - Data Lakes WorkshopQcon Rio 2015 - Data Lakes Workshop
Qcon Rio 2015 - Data Lakes Workshop
 
Data Lakes com Hadoop e Spark: Agile Analytics na prática
Data Lakes com Hadoop e Spark: Agile Analytics na práticaData Lakes com Hadoop e Spark: Agile Analytics na prática
Data Lakes com Hadoop e Spark: Agile Analytics na prática
 
DB2 bufferpool Pagefixing por Alvaro Salla
DB2 bufferpool Pagefixing  por Alvaro SallaDB2 bufferpool Pagefixing  por Alvaro Salla
DB2 bufferpool Pagefixing por Alvaro Salla
 
hibernate annotation
hibernate annotationhibernate annotation
hibernate annotation
 
Mongo Db - PHP Day Workshop
Mongo Db - PHP Day WorkshopMongo Db - PHP Day Workshop
Mongo Db - PHP Day Workshop
 
Design Patterns para Tuning Pentaho com Ctools
Design Patterns para Tuning Pentaho com CtoolsDesign Patterns para Tuning Pentaho com Ctools
Design Patterns para Tuning Pentaho com Ctools
 
PostgreSQL-Prático.pdf
PostgreSQL-Prático.pdfPostgreSQL-Prático.pdf
PostgreSQL-Prático.pdf
 
Amostra Resolucao da Prova Sefaz 2007 Prof Jaime
Amostra   Resolucao da Prova Sefaz 2007   Prof JaimeAmostra   Resolucao da Prova Sefaz 2007   Prof Jaime
Amostra Resolucao da Prova Sefaz 2007 Prof Jaime
 

Mais de Tiago Simões

How to go the extra mile on monitoring
How to go the extra mile on monitoringHow to go the extra mile on monitoring
How to go the extra mile on monitoringTiago Simões
 
How to create a secured multi tenancy for clustered ML with JupyterHub
How to create a secured multi tenancy for clustered ML with JupyterHubHow to create a secured multi tenancy for clustered ML with JupyterHub
How to create a secured multi tenancy for clustered ML with JupyterHubTiago Simões
 
How to scheduled jobs in a cloudera cluster without oozie
How to scheduled jobs in a cloudera cluster without oozieHow to scheduled jobs in a cloudera cluster without oozie
How to scheduled jobs in a cloudera cluster without oozieTiago Simões
 
How to create a secured cloudera cluster
How to create a secured cloudera clusterHow to create a secured cloudera cluster
How to create a secured cloudera clusterTiago Simões
 
How to create a multi tenancy for an interactive data analysis with jupyter h...
How to create a multi tenancy for an interactive data analysis with jupyter h...How to create a multi tenancy for an interactive data analysis with jupyter h...
How to create a multi tenancy for an interactive data analysis with jupyter h...Tiago Simões
 
How to implement a gdpr solution in a cloudera architecture
How to implement a gdpr solution in a cloudera architectureHow to implement a gdpr solution in a cloudera architecture
How to implement a gdpr solution in a cloudera architectureTiago Simões
 
How to configure a hive high availability connection with zeppelin
How to configure a hive high availability connection with zeppelinHow to configure a hive high availability connection with zeppelin
How to configure a hive high availability connection with zeppelinTiago Simões
 
How to install and use multiple versions of applications in run-time
How to install and use multiple versions of applications in run-timeHow to install and use multiple versions of applications in run-time
How to install and use multiple versions of applications in run-timeTiago Simões
 
How to create a multi tenancy for an interactive data analysis
How to create a multi tenancy for an interactive data analysisHow to create a multi tenancy for an interactive data analysis
How to create a multi tenancy for an interactive data analysisTiago Simões
 

Mais de Tiago Simões (9)

How to go the extra mile on monitoring
How to go the extra mile on monitoringHow to go the extra mile on monitoring
How to go the extra mile on monitoring
 
How to create a secured multi tenancy for clustered ML with JupyterHub
How to create a secured multi tenancy for clustered ML with JupyterHubHow to create a secured multi tenancy for clustered ML with JupyterHub
How to create a secured multi tenancy for clustered ML with JupyterHub
 
How to scheduled jobs in a cloudera cluster without oozie
How to scheduled jobs in a cloudera cluster without oozieHow to scheduled jobs in a cloudera cluster without oozie
How to scheduled jobs in a cloudera cluster without oozie
 
How to create a secured cloudera cluster
How to create a secured cloudera clusterHow to create a secured cloudera cluster
How to create a secured cloudera cluster
 
How to create a multi tenancy for an interactive data analysis with jupyter h...
How to create a multi tenancy for an interactive data analysis with jupyter h...How to create a multi tenancy for an interactive data analysis with jupyter h...
How to create a multi tenancy for an interactive data analysis with jupyter h...
 
How to implement a gdpr solution in a cloudera architecture
How to implement a gdpr solution in a cloudera architectureHow to implement a gdpr solution in a cloudera architecture
How to implement a gdpr solution in a cloudera architecture
 
How to configure a hive high availability connection with zeppelin
How to configure a hive high availability connection with zeppelinHow to configure a hive high availability connection with zeppelin
How to configure a hive high availability connection with zeppelin
 
How to install and use multiple versions of applications in run-time
How to install and use multiple versions of applications in run-timeHow to install and use multiple versions of applications in run-time
How to install and use multiple versions of applications in run-time
 
How to create a multi tenancy for an interactive data analysis
How to create a multi tenancy for an interactive data analysisHow to create a multi tenancy for an interactive data analysis
How to create a multi tenancy for an interactive data analysis
 

Hive vs impala vs spark - tuning

  • 1. Hive vs Impala vs Spark Performance Tuning
  • 2. Intro Nesta apresentação serão abordados vários pontos que devem ser tidos em consideração na arquitectura, configuração e optimização nas plataformas Hive, Impala e Spark.
  • 4. Recursos O ajuste das parametrizações do YARN devem ter em conta o uso de vCores e memória, configurando os containers, por forma a usar todos os recursos disponíveis, além daqueles necessários para sobrecarga e outros serviços.
  • 5. Recursos Configuração de memória do YARN e MapReduce Deverão ser tido em conta os seguintes valores: ● RAM (quantidade de memória) ● CORES (Número de núcleos de CPU) ● DISKS (número de discos) A RAM total disponível para o YARN e MapReduce deve considerar a Memória Reservada. A memória reservada é a RAM necessária para os processos do sistema e outros processos do Hadoop (como o HBase). Memória Reservada = Reserved for stack memory + Reserved for HBase Memory (se o HBase estiver no mesmo nó). Para cálculo da Memória Reservada por nó, pode ser usada como referência a tabela..
  • 7. Recursos Calculo do nº máximo de containers por nó Nº containers = min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE). Calculo Java heap memory do Application Master e Container O heap memory size deverá ser 80% do tamanho do container, i.e. do yarn.app.mapreduce.am.resource.mb e yarn.nodemanager.resource.memory-mb respectivamente. NOTA: DISKS é referente a dfs.data.dirs (número de discos) por máquina e MIN_CONTAINER_SIZE é o tamanho mínimo do container (na RAM).
  • 8. Recursos Calculo RAM por containers RAM por container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers). Exemplo: Calculo Hive Memory Map Join hive.auto.convert.join.noconditionaltask.size = 33% do tamanho do container
  • 9. Recursos Exemplo de configuração de memória do YARN e MapReduce Por intermédio de uma ferramenta da Hortonworks é possível Ter uma base de trabalho das parametrizações: python hdp-configuration-utils.py -c 4 -m 45 -d 2 -k False Options: -c CORES, Number of cores on each host -m MEMORY, Amount of Memory on each host in GB -d DISKS, Number of disks on each host -k HBASE, True if HBase is installed, False is not
  • 10. Arquitectura dos Dados A estrutura dos dados é um ponto fulcral na optimização. Particionamento dos Dados Conforme imagem, pese embora seja opcional a estruturação em partições e/ou buckets - tem um impacto muito positivo na performance final da query especialmente quando esta tem filtros (Where = ‘XXX’). Exemplo: Create Table sale(id in, amount decimal) Partitioned By (xdate string, state string);
  • 11. Arquitectura dos Dados Bucketing Permite a divisão dos dados (uma partição) em n (ex: 32) ficheiros por intermédio de uma função de hash sobre a chave escolhida. Ideal para uma distribuição uniforme dos dados, tornando os Map-side joins muito mais eficientes Exemplo: set hive.enforce.bucketing = true; Create Table bucketed_table (Col1 integer, Col2 string, Col3 string, Col4 date, … ) Partitioned By (col4 date) Clustered By (Col1) INTO 32 BUCKETS Stored As Parquet TBLPROPERTIES ( parquet.compress'=snappy, 'transactional'='true', 'hive.exec.dynamic.partition'='true', 'hive.exec.dynamic.partition.mode'='nonstrict', 'hive.compactor.initiator.on'='true', 'hive.exec.max.dynamic.partitions.pernode'='150' );
  • 12. Arquitectura dos Dados Formato dos Dados Por questões de transversalidade Hive/Impala formato recomendado é o parquet. O parquet tem uma compressão eficiente e leitura rápida, um dos pontos que devem ser tidos em consideração é o tamanho do disk block/row group/file size no HDFS, que deverá ser entre 512 a 1024 MB. Exemplo: ALTER SYSTEM SET `store.parquet.block-size` = 1073741824; Create Table addresses ( name string, street string, city string, state string, zip int ) STORED AS Parquet tblproperties ("parquet.compress"="snappy"); Caso a ingestão seja feita em formato texto é sempre possível efectuar uma View sobre os dados já existentes. Exemplo: Create Table TABLE_PARQUET STORED AS Parquet AS SELECT * FROM TABLE_CSV;
  • 13. Arquitectura da Query A forma como é efectuada a query deverá ser estar o mais correlacionada possível com a estrutura dos dados. JOINS De forma standardizada o JOIN é efectuado conforme imagem. Cada JOIN deve ser analisado e por intermédio de hints e parâmetros é possível alterar a forma como o Hive interpreta o JOIN e a performance destes respectivamente . Exemplo: Select /*+ MAPJOIN(c) */ * FROM orders o JOIN cities c ON (o.city_id = c.id);
  • 14. Arquitectura da Query JOINS Com o MAPJOIN permite que a tabela seja carregada para memória, permitindo que a operação seja feita dentro do Mapper sem o uso do passo Mapper/Reducer. Nota: Antes da execução de qualquer query todas as tabelas envolvidas devem ter as estatísticas actualizadas. Exemplo: Tabela: ANALYZE TABLE <table_name> COMPUTE STATISTICS; ANALYZE TABLE <table_name> COMPUTE STATISTICS for COLUMNS; Colunas: ANALYZE TABLE <table_name> partition (coll="x") COMPUTE STATISTICS for COLUMNS;
  • 15. Arquitectura da Query Escolha - JOIN Conforme a tabela indica existem prós e contras para cada tipo de JOIN, como tal a escolha deve ser ponderada de acordo com a realidade de cada query e respectivo modelo.
  • 16. Arquitectura da Query Shuffle JOIN Broadcast JOIN Sort Merge-Bucket JOIN
  • 17. Arquitectura da Query Parametros - JOIN set hive.exec.dynamic.partition.mode=nonstrict; set hive.exec.max.dynamic.partitions=10000; set hive.exec.max.dynamic.partitions.pernode=500; set hive.auto.convert.join.noconditionaltask = true; set hive.auto.convert.join.noconditionaltask.size = 10000; set hive.optimize.correlation=true; set hive.smbjoin.cache.rows=15000; set hive.auto.convert.join.noconditionaltask.size=20971520; set hive.mapjoin.localtask.max.memory.usage = 0.999; set hive.mapjoin.smalltable.filesize = 30000000; set hive.mapjoin.lazy.hashtable=false; set hive.exec.parallel=true; set hive.auto.convert.join = true; JOIN Tabelas - com Bucketing set hive.optimize.bucketmapjoin = true; set hive.optimize.bucketmapjoin.sortedmerge = true; set hive.input.format = org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat; set hive.optimize.bucketmapjoin = true;
  • 18. Arquitectura da Query Parametros Genéricos Vectorization set hive.vectorized.execution.enabled=true; set hive.vectorized.execution.reduce.enabled = true; set hive.exec.dynamic.partition = true; set hive.exec.dynamic.partition.mode = nonstrict; set hive.optimize.sort.dynamic.partition=true; set hive.optimize.reducededuplication=true; set hive.optimize.index.filter=true; Cost-Based Optimizer & Statistics set hive.compute.query.using.stats=true; set hive.prewarm.enabled=true; set hive.cbo.enable=true; set hive.fetch.task.conversion=more; set hive.fetch.task.conversion.threshold=1073741824; set hive.stats.autogather=true; set hive.stats.fetch.column.stats=true; set hive.stats.fetch.partition.stats=true; set hive.stats.autographer=true;
  • 20. Recursos Conforme imagem, conceptualmente o Hive on Spark é mais eficiente que o MapReduce pois evita os passos intermédios em HDFS e em vez disso usa a memória. Como tal alguns pontos que devem ser considerados/configurados. Exemplo:
  • 21. Recursos Executors Por forma não existirem desperdícios de recursos é recomendável que existam fat executors, i.e. menos executores mas cada um com mais cores, isto permite uma melhor utilização da memória. Memory Para além do tamanho do container deverá ser tido em conta o tamanho do Driver (spark.driver.memory) e respectivo overhead (spark.yarn.driver.memoryOverhead) que deverá ser pelo menos 20% do driver.
  • 22. Recursos Para um Use Case de uma VM Cloudera - 37Gb Memória e 4 Cores Parametros set hive.execution.engine=spark; set yarn.nodemanager.resource.cpu-vcores=2; set yarn.nodemanager.resource.memory-mb=16384; set yarn.scheduler.maximum-allocation-vcores=4; set yarn.scheduler.minimum-allocation-mb=4096; set yarn.scheduler.maximum-allocation-mb=10192; set spark.executor.memory=1684354560, set spark.yarn.executor.memoryOverhead=1000; set spark.driver.memory=10843545604 set spark.yarn.driver.memoryOverhead=800; set spark.executor.instances=10; set spark.executor.cores=2; set hive.spark.dynamic.partition.pruning.map.join.only=true; set hive.exec.reducers.bytes.per.reducer=6001088640;
  • 24. Impala O Impala é semelhante em alguns aspectos com o Hive, i.e. partilha os metadados e em parte a sintaxe., porém em vez do MapReduce usa a memória. Nota: Algumas funções e tipos de dados não funcionam ou são diferentes entre o Hive e o Impala. À semelhança do Hive, no Impala é igualmente importante a escolha da Arquitectura dos Dados assim como a da própria Query.
  • 25. Arquitectura dos Dados A estrutura dos dados é um ponto de partida para a optimização. Em termos do modelo devem ser tidos em consideração os seguintes aspectos: ● Particionamento ● Sorting ● Runtime filter and dynamic partition pruning ● Tipos de Dados ● Flat vs Nested Particionamento Visto que o Impala e o Hive partilham os metadados, a granularidade deve ser bem ponderada. Baixa de mais afeta o paralelismo e alta de mais irá criar bottlenecks no HDFS NameNode, Hive Metastore e no Impala catalog service.
  • 26. Arquitectura dos Dados Sorting Com a criação da tabela com um Sort inicial, irá funcionar de forma complementar ao particionamento existente pois pode não só evitar o over-partitioning de uma tabela, assim como torna muito mais eficientes pesquisas de min/max.
  • 27. Arquitectura dos Dados Runtime filter e dynamic partition pruning Por intermédio dos filtros permite optimizar JOINs entre uma tabela grande e outra que seja pequena (conforme imagem). Após uma primeira execução alguns parâmetros que devem ser considerados e testados são: ● RUNTIME_FILTER_MODE ● MAX_NUM_RUNTIME_FILTERS ● DISABLE_ROW_RUNTIME_FILTERING ● RUNTIME_FILTER_MAX_SIZE ● RUNTIME_FILTER_MIN_SIZE ● RUNTIME_BLOOM_FILTER_SIZE
  • 28. Arquitectura dos Dados Tipos de Dados O tipo de dados escolhidos afecta tanto ao nível da computação da query como do próprio espaço ocupado no HDFS. Sempre que possível devem ser escolhidos tipo de dados numéricos e o formato Parquet. Nota: Os tipo de de dados CHAR, TIMESTAMP, TINYINT não são suportados no Impala.
  • 29. Arquitectura dos Dados Flat vs Nested Conforme é possível verificar pela imagem, a elaboração do modelo de dados tem um grande impacto na performance. Relações 1-n idealmente devem ser representadas como nested tables e usar sempre que possível nested aggregates em vez de nested data, fazendo com que os JOINs hierárquicos tenham um custo muito mais baixo. Exemplo:
  • 30. Arquitectura da Query A forma como é efectuada a query deverá ser estar o mais correlacionada possível com a estrutura dos dados. JOINS Por forma a se obter os melhores resultados a nível de performance devem ser tidos em conta os seguintes pontos: ● JOIN que minimiza o uso dos recursos (Broadcast/Partition). ● Identificar os JOINs que beneficiam de Runtime filters. ● A ordem dos JOINs
  • 31. Arquitectura da Query Um dos aspectos mais importantes na execução de uma query é ser feito à priori, i.e. a computação de todas as estatísticas das tabelas envolvidas. Statistics Por forma a que o Impala consiga fazer a melhor análise das estatísticas (Explain Plain) é fulcral ter de antemão a computação das mesmas. Exemplo: COMPUTE STATS SALES_PART_2 PARTITION (Region,Country); COMPUTE INCREMENTAL STATS SALES_PART_2 PARTITION (Region,Country); Nota: Incremental Stats apenas aplica-se a tabelas particionadas.
  • 32. Arquitectura da Query Hints Os hints são usualmente usados em queries pesadas, quando as estatísticas não estão devidamente actualizadas ou por outros factores que estejam a afectar a performance. Nota: Servem como sugestões e não como directivas. Caso se pretenda forçar o uso do hint no JOIN deverá ser incluido straight_join no Select. Hints JOIN /* +SHUFFLE */ Indica que deve ser usada técnica de particionamento no JOIN. /* +BROADCAST */ Faz com que o conteúdo do lado direito do JOIN seja enviado para todos os nós envolvidos no processamento (Default). Exemplo: Select straight_join t1.name, t2.id, t3.price from t1 join /* +shuffle */ t2 join /* +broadcast */ t3 on t1.id = t2.id and t2.id = t3.id;
  • 33. Arquitectura da Query INSERT/SELECT /* +SHUFFLE */ Apenas um nó irá escrever, reduzindo a fragmentação, i.e. minimizando o número de ficheiros, assim como o número de buffers em memória (Default). /* +NOSHUFFLE */ Desactiva o re-particionamento, o Explain Plan poderá ser mais rápido mas também poderá gerar muito mais ficheiros com poucos dados. /* +CLUSTERED */ Ordena os dados, por forma a assegurar que apenas uma partição é escrita por cada nó. /* +NOCLUSTERED */ Não ordena os dados, recomendável para tabelas Kudu (Default). HDFS Por forma a influenciar a forma como o Impala processa os Blocos de Dados do HDFS é possível por intermédio: * +SCHEDULE_CACHE_LOCAL */, /* +SCHEDULE_DISK_LOCAL */ ou /* +SCHEDULE_REMOTE */. Sendo ainda possível combinar com a hint /* +RANDOM_REPLICA */ que activa um desempate random na escolha dos blocos HDFS. Exemplo: Select * /* +SCHEDULE_CACHE_LOCAL,RANDOM_REPLICA */ from table;
  • 34. Arquitectura da Query HDFS Caching Com o caching de dados em memória permite que o Impala leia a informação directamente da memória evitando leituras ao HDFS, trazendo alguns improvements na performance (Conforme imagem). O caching pode ser feito de uma tabela inteira ou apenas de uma partição, sendo ainda possível indicar o nº de hosts (replication = x). Nota: Esta técnica não é aplicável a tabelas HBase, S3, Kudu, ou Isilon. Exemplo: HDFS hdfs cacheadmin -addPool pool_1 -owner impala -limit 4000000000 IMPALA alter table SALES_PART partition (year=1960) set cached in 'pool_1' ; alter table SALES_PART set cached in 'pool_1' with replication = 3;
  • 35. Arquitectura da Query Parametros Genéricos set mem_limit=13221225472; set query_timeout_s = 1000; set optimize_partition_key_scans = true; set exec_single_node_rows_threshold = 20000; set default_join_distribution_mode = 1; set max_num_runtime_filters = 100; set rm_initial_mem = 1000000; set runtime_filter_wait_time_ms = 600; set strict_mode = true; set disable_row_runtime_filtering = true; set sync_ddl = true; set batch_size=1000; set num_nodes = ''; set max_scan_range_length=0; set num_scanner_threads = 0;
  • 36. Spark
  • 37. Recursos Conceptualmente a configuração dos recursos no Spark são semelhantes ao que foi dito na secção do Hive on Spark. Porém é necessário ressalvar que caso seja configurado um executor de 10Gb o Spark irá criar uma JVM conforme imagem, i.e. por forma a prevenir erros de falta memória (00Ms) apenas 90% é configurável (“Safety” - spark.storage.safetyFraction). Posteriormente temos efectivamente “Storage” - spark.storage.memoryFraction e “Shuffle” - spark.shuffle.memoryFraction, que por default são respectivamente 60% e 20%. Concluindo dos iniciais 10Gb, temos apenas 5.4Gb (JVM*90%*60%). Internamente existe outra configuração “shuffle” - spark.shuffle.safetyFraction que é 80% da JVM Heap, i.e. 80%*20% - 1.6Gb. Esta área de memória é usada para agregações pré-reduce (reduceByKey), caso os resultados não caibam nesta área o Spark irá escrever no HDFS. A nível dos parâmetros de uma JVM que devem ser também considerados, especialmente se esta tiver menos de 32Gb é a flag -XX:+UseCompressedOops pois em termos de optimização faz com que os apontadores passem a ser de 4 Bytes ao invés de 8 Bytes (Default).
  • 38. Recursos Memória No Spark o uso da memória pode de uma forma grosseira ser dividido em três blocos: ● Caching (.cache ou .persist) ● Shuffle (buffering de dados entre nós) ● Tasks (.map) E para cada situação os parâmetros podem e devem ser ajustados. Exemplo: Low cluster memory sparkConf.set("spark.storage.memoryFraction", "0.1") sparkConf.set("spark.shuffle.memoryFraction", "0.2") Shuffle intensive jobs sparkConf.set("spark.storage.memoryFraction", "0.1") sparkConf.set("spark.shuffle.memoryFraction", "0.8") Computation intensive jobs sparkConf.set("spark.storage.memoryFraction", "0.1") sparkConf.set("spark.shuffle.memoryFraction", "0.6")
  • 39. Recursos Caching No Spark é fulcral evitar a escrita no HDFS, para tal o recomendável é o caching data e conforme imagem existem diversas técnicas e com diversos resultados: ● MEMORY_ONLY - Dados como objectos Java. Em termos de espaço é pouco eficiente mas é o mais rápido. ● MEMORY_ONLY_SER - Dados serializados, porém existe o custo CPU (serialized/deserialized). ● MEMORY_AND_DISK_SER - Dados serializados, porém tudo o que não caiba em memória será escrito no HDFS. Uma boa opção caso exista alto processamento envolvido ou joins/reduces antes de caching. ● DISK_ONLY - Dados em HDFS. Nota: Por default o serializer é em Java, sendo recomendável o Kryo Serializer Exemplo: rdd.cache() ou rdd.persist(storageLevel.MEMORY_ONLY). sparkConf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") sparkConf.set("spark.storage.memoryFraction", "0.6") sparkConf.set("spark.shuffle.memoryFraction", "0.2")
  • 40. Recursos GC À medida que um Job Spark é executado e existe a persistência de objectos em caching que irá conduzir a um aumento do consumo de memória e por sua vez despoleta mais tentativas de GC, nestas situações recomenda-se que sejam libertados todos e quaisquer RDD’s que já não estejam a ser usados. Um dos factores que também influencia a eficiência do GC é a técnica usada: ● Serial GC (-XX:+UseSerialGC) ● Parallel GC (-XX:+UseParallelGC) ● Parallel Old GC (-XX:+UseParallelOldGC) ● Concurrent Mark Sweep (CMS) Collector (-XX:+UseConcMarkSweepGC) ● G1 Garbage Collector (-XX:+UseG1GC) Sendo o recomendado o G1, pois é o que lida melhor com a flutuação dos heap sizes e apresenta melhor taxa de transferência e baixa latência. Exemplo: sparkConf.set("spark.executor.extraJavaOptions", "-XX:+UseG1GC")
  • 41. Arquitectura Particionamento e Paralelismo No processamento é recomendável a configuração de 2-3 tasks por CPU core. Os RDD’s são tipicamente particionados com base no número de blocos HDFS ocupados. Por intermédio dos mecanismos de particionamento permite reduzir o número de shuffles, sendo estes: ● Hash partitioning - As keys que têm o mesmo hash estão no mesmo nó. ● Range partitioning - As keys que se encontram dentro do mesmo range estão no mesmo nó. Pouco particionamento faz com que não seja dado o uso correcto ao paralelismo(Data skewing e/ou Less concurrency), já em excesso faz com que as tasks demorem mais do que é suposto (Task scheduling). Usualmente o número ronda entre 2x o número de cores no Cluster e 100k partições. Com o correcto particionamento tem igualmente um impacto muito positivo em operações de shuffling data (cogroup(), groupWith(), join(), groupByKey(), combineByKey(), reduceByKey(), and lookup()).
  • 42. Arquitectura Particionamento e Paralelismo É necessário conhecer bem o Job que estamos a correr. Conforme imagem, por default os valores dos parâmetros spark.default.parallelism=12 e spark.sql.shuffle.partitions=200, para o cálculo adequado destes parâmetros é necessário identificar na timeline do Job se existem tasks com bastante scheduler delay deverá ser reduzido o shuffle partition. Nº Partições = Total input dataset size / partition size Nível de Localidade A localidade dos dados e respectivo processamento tem um impacto directo na performance do Job, quanto mais próximos (Dados/Processamento) melhor. ● PROCESS_LOCAL - Execução no mesmo processo que a fonte de dados. ● NODE_LOCAL - Execução no nó da fonte de dados. ● RACK_LOCAL - Execução no rack da fonte de dados. ● ANY - Em qualquer sítio na rede. Em algumas situações (streaming) poderá ser necessário um ajuste do delay do cálculo da localidade, i.e. através do parâmetro spark.locality.wait, que por default é de 3s e poderá ser ajustado para 0-0.5.
  • 43. Arquitectura Acções/Transformações As acções/transformações é uma das fases no Spark que requerem especial atenção. Sempre que possível devem ser usadas transformações Narrow (ex: map() e filter()) em invez das Wide, pois conforme se observa na imagem operações como groupByKey(), reduceByKey() e join() implicam múltiplas partições e shuffling. Caso sejam necessárias transformações Wide podem ser feitas algumas optimizações, tais como por exemplo: ● No Join() por forma a minimizar o shuffling deve ser feito broadcasting o grupo de dados mais pequeno ou hash partitioning de ambos os RDD pelas respectivas chaves. ● Redução associativa deve ser usado reduceByKey() e evitar groupByKey(). ● Junção de dois datasets agrupados e mantém-los agrupados deve ser usado o cogroup() ao invés do flatMap-join-groupBy(). ● Re-particionamento de dados deverá ser feito com repartitionAndSortWithinPartitions() ao invés de se feio separadamente o re- particionamento e posteriormente o sort a cada partição pois fará com que exista comparativamente mais operações de shuffling.
  • 44. Arquitectura Dataset/Dataframe Para Jobs que operem com instruções SQL, Dataframes/Datasets é o caminho a escolher, pois a API contém muitas optimizações por forma a que estas estruturas operem de forma semelhante a uma tabela do modelo relacional (ex: Tabelas Hive, HDFS, etc...). O dataframe porém apresenta algumas limitações que devem ser tidas em consideração: ● A API do SparkSQL não permite a compilação time type safety. ● Após a transformação de um RDD em DF não é possível a sua regressão. Exemplo:
  • 45. Arquitectura Sorting Tendo como objectivo final a escrita de queries SQL com JOIN’s no SparkSQL pode ser benéfico fazer o sort à prior aos dados nos dataframes Exemplo: Distribute By SET spark.sql.shuffle.partitions = 2 df.repartition($"key", 2) Cluster By (Distribute By + Sort By) SET spark.sql.shuffle.partitions = 2 df .repartition($"key", 2).sortWithinPartitions() Broadcasting Variables Tendo em consideração a arquitectura e a localização dos dados deverá ser considerada a possibilidade da distribuição das variáveis pelos diversos nós, por exemplo dados de referência. Exemplo val b = sc.broadcast(1); b: org.apache.spark.broadcast.Broadcast[Int] = Broadcast(0) Sort By df.sortWithinPartitions() Skewed Data SET spark.sql.shuffle.partitions = 5 SELECT * FROM df DISTRIBUTE BY key, value
  • 46. SQL HiveContext No Spark mais concretamente com a API HiveContext é possível aceder aos metadados em Hive e assim como proceder a algumas optimizações à semelhança do que foi feito no Hive on Spark. Exemplo: hiveCtx = HiveContext(sc) hiveCtx.sql("SET yarn.nodemanager.resource.cpu-vcores=4") hiveCtx.sql("SET yarn.nodemanager.resource.memory-mb=16384") hiveCtx.sql("SET yarn.scheduler.maximum-allocation-vcores=4") hiveCtx.sql("SET yarn.scheduler.minimum-allocation-mb=4096") hiveCtx.sql("SET yarn.scheduler.maximum-allocation-mb=8192")
  • 47. SQL JOINS Usualmente são a grande fonte de problemas de performance: ● Shuffle Hash ● Broadcast Hash ● Skew (Data skew) ● Cartesian ● One to Many ● Theta Shuffle Hash é usado quando existe uma distribuição uniforme das chaves e assim como o paralelismo usado. Quando não é o caso conforme imagem, uma possível solução pode passar para Broadcast se um dos dataframes couber em memória ou por sua vez filtrar os dados. Broadcast Hash é maior parte das vezes melhor que o Shuffle Hash, para tal deve-se validar no Explain Plan se o Spark está a usá-lo, uma optimização que pode e deve ser feita é o caching do dataframe mais pequeno.
  • 48. SQL JOINS Skew é usado quando existe data skew , i.e. uma distribuição não- uniforme das partições, que num JOIN implica shuffling e é mau para a performance. É possível melhorar esta situação por intermédio de hints por forma a que o Spark construa uma explain plan melhor. Exemplo: Tabela com Skew Select /*+ SKEW('orders') */ * From orders, customers Where c_custId = o_custId Tabela com Skew - Apenas às colunas do JOIN Select /*+ SKEW('orders', ('o_custId', 'o_storeRegionId')) */ * From orders, customers Where o_custId = c_custId And o_storeRegionId = c_regionId Cartesian é muitas vezes um problema camuflado, pois em termos de output, conforme imagem é algo que pode implodir rapidamente. Um possível workaround a esta situação é: ● Criação de um RDD com os UID por UID. ● Forçar o Broadcast às linhas da tabela. ● Executar uma UDF dado o UID por UID que procura na tabela e efectua o respectivo processamento.
  • 49. SQL JOINS One to Many Join à semelhança do produto cartesiano também pode implodir no número de resultados, pelo que deixa de ser um problema desde que seja usado parquet nas tabelas. Theta Join é um JOIN peculiar que implica um conjunto de loops por forma a validar a condição na cláusula ON. Uma forma de optimizar é a criação de buckets para o matching da condição ON. Exemplo: ON(Car_Price >= Boat_Price) ON(KeyA < KeyB + 1000)
  • 50. SQL Bucketing Conforme mencionado no Theta Join e na secção Hive - Arquitectura de Dados, bucketing é uma solução elegante para JOIN’s, i.e. por exemplo chaves que são usadas em vários JOIN’s (ID’s, etc…) i.e.: Bucketing = pre (Shuffle + Sort) nas Chaves dos JOIN’s Porém, conforme imagens o bucketing do Spark é conceptualmente diferente e não é compatível com o do Hive. Em termos de performance é expectável obter ganhos 2x a 5x após bucketing. Exemplo: set spark.sql.sources.bucketing.enabled = true Dataframe API df.write.bucketBy(numBuckets,”col1”,...).sortBy(“col1”,...).saveAsTable(“bucketed_Table” ) SQL Statement Create Table bucketed_table(col1 int, …) using Parquet Clustered By (col1, …) Sorted By (col1, …) Into X Buckets
  • 51. SQL Parametros Genéricos hiveCtx = HiveContext(sc) hiveCtx.sql("set spark.executor.memory=1638454560") hiveCtx.sql("set spark.yarn.executor.memoryOverhead=1000") hiveCtx.sql("set spark.driver.memory=10843545604") hiveCtx.sql("set spark.yarn.driver.memoryOverhead=1000") hiveCtx.sql("set spark.executor.instances=12") hiveCtx.sql("set spark.executor.cores=4") hiveCtx.sql("set spark.sql.shuffle.partitions = 1") hiveCtx.sql("set spark.default.parallelism = 12") hiveCtx.sql("set spark.locality.wait = 0") hiveCtx.sql("set spark.sql.autoBroadcastJoinThreshold=1048576000") hiveCtx.sql("set spark.serialize = org.apache.spark.serializer.KryoSerializer") hiveCtx.sql("set spark.storage.memoryFraction = 0.6") hiveCtx.sql("set spark.shuffle.memoryFraction = 0.3") hiveCtx.sql("set spark.executor.extraJavaOptions = -XX:+UseG1GC")
  • 52. Aqui é demonstrado as grandes vantagens da execução de um job em Spark e/ou em memória vs tradicional MapReduce
  • 53. Resumo ● Escolher as Arquitecturas correctas ● Recursos Disponíveis vs Necessários ● Evitar Shuffling Data e GC
  • 54. Conclusão Tune the job not the Cluster!