[colmena] experiencia de ajuste de colmena

1. Hive se optimiza a sí mismo

Optimizado para comandos como union

2. Tasa de localización de datos

La tasa de localización de datos de HDFS afecta el rendimiento de la colmena

En el caso de un tamaño de datos determinado, 500 archivos de 128M y 2 archivos de 30G ejecutan tareas de colmena, y el rendimiento es diferente. La mayor diferencia entre los dos es que el último debe transmitirse a través de la red al leer archivos, mientras que El primero es de lectura y escritura local. Problemas de tasa de localización de datos.

imagen.png

3. Formato de datos

Hive proporciona texto, archivo de secuencia, archivo RC, ORC, Parquest y otros formatos.

  • SequenceFile es un archivo plano con una estructura binaria de par clave/valor, que se usa ampliamente en MapReduce.
  • Parquet es un formato de almacenamiento en columnas compatible con múltiples motores de datos, MapReduce y Spark.
  • Una optimización de RCFile en ORC, una de las opciones principales.

4. Particionamiento y agrupamiento

1. Tabla de particiones:

Resumen: El significado de la tabla de particiones es realmente muy simple de entender. Es crear una carpeta en el sistema y poner los datos clasificados en diferentes carpetas para acelerar la velocidad de consulta.

Comprenda que las particiones son carpetas divididas y conquistadas. Al consultar, se pueden usar como nombres de columna para mostrar el alcance de la consulta.

  • Punto clave 1: particionado por (dt String, cadena de país); al crear la tabla, especifique que se trata de una tabla particionada. Se creará un directorio de dos niveles, el primer nombre de directorio y las reglas de nombre de directorio de segundo nivel

Las columnas definidas en la cláusula PARTITIONED BY son columnas formales en la tabla y se convierten en columnas de partición. Pero no hay tales valores en el archivo de datos, solo representa el directorio.

  • Punto clave 2: partición (dt='2001-01-01',country='GB'); Al cargar datos, cargue los datos en diferentes particiones respectivamente. Es decir, se colocan en diferentes subdirectorios.

2. Tabla de particiones dinámicas: 

关闭严格分区模式
动态分区模式时是严格模式,也就是至少有一个静态分区。
set hive.exec.dynamic.partition.mode=nonstrict    //分区模式,默认nostrict
set hive.exec.dynamic.partition=true            //开启动态分区,默认true
set hive.exec.max.dynamic.partitions=1000        //最大动态分区数,默认1000
复制代码

¿Por qué usar particiones dinámicas? Tomemos un ejemplo: si China tiene 50 provincias, cada provincia tiene 50 ciudades y cada ciudad tiene 100 distritos, ¿cuánto tiempo nos llevará usar particiones estáticas para terminar? Todos queremos utilizar el particionamiento dinámico.

动态分区默认是没有开启。开启后默认是以严格模式执行的,在这种模式下需要至少一个分区字段是静态的。 这有助于阻止因设计错误导致导致查询差生大量的分区。列如:用户可能错误使用时间戳作为分区表字段。然后导致每秒都对应一个分区!这样我们也可以采用相应的措施:

3. 分桶表:

每一个表或者分区,Hive可以进一步组织成桶。也就是说,桶为细粒度的数据范围划分。

分桶规则:对分桶字段值进行哈希,哈希值除以桶的个数求余,余数决定了该条记录在哪个桶中,也就是余数相同的在一个桶中。分桶不会改变原有表和原有分区目录的组织方式。只是更改了数据在文件中的分布。

优点:1、提高join查询效率 2、提高抽样效率

可以用 desc formatted [表名] 来查看目录组织方式
复制代码

五、 干预sql的运行方式

  • 改写sql,实现对计算引擎执行过程的调优
  • 通过sql-hint语法,实现对计算引擎执行过程的干预
  • 通过数据库开放的一些配置,实现对计算引擎的干预

  具体如下:

1. 使用grouping sets grouping__id rollup cube等代替group by +union all

hive对group by+ union all的写法进行了优化
复制代码

2.使用 group by 来代替 distinct

在数据没有发生数据倾斜的情况下,采用distinct要比group by要好

默认情况下,distinct会被hive翻译成一个全局唯一reduce任务来做去重操作,因而并行度为1,而且有导致数据倾斜的可能。

而group by则会被hive翻译成分组聚合运算,会有多个reduce任务并行处理,每个reduce对收到的一部分数据组,进行每组聚合(去重)

注意:最新的hive版本中:新增了对count(distinct)的优化,通过配置hive.optimize.countdistinct

即使真的出现数据倾斜也可以自动优化。

3 .使用Hinit

使用mapjoin(b) 括号中指定的是数据量较小的表,表示在map阶段完成a,b两表的连接。

将原来在Reduce中进行的连接操作,前推到了Map阶段。

SELECT /* + MAPJOIN(b) */ a.key,a.value
FROM a
JOIN b ON a.key = b.key;
复制代码

大表在右边使用streamtable的sql

--STRSEAMTABLE(),括号中指定数据量大的表
--默认情况下,在reduce阶段进行连接,hive把坐标中的数据放在缓存中,右表的数据作为流数据表
SELECT /*+ STREAMTABLE(a) */ a.val,b.val,c.val
FROM a
JOIN b ON (a.key = b.key)
JOIN c ON (c.key = b.key)
复制代码

普通表的join又被称为 Replartition Join,通常shuflle操作发生在此阶段

也可以通过设置hive.smalltable.filesize or hive.mapjoin.smalltable.filesize 
如果大小表在进行连接时,小表连接小于这个默认值,则自动开启Mapjoin优化,
复制代码

六、配置的一些优化

1. 开启向量化

默认是关闭的,将一个普通的查询转化为向量化查询。大大减少了扫描,过滤等查询,标准查询时系统一次处理一行,矢量化查询可以一次性查询1024行数据,减少了系统上下文切换的开销。

set hive.vectorized.execution.enabled=true;
目前mapreduce只支持map端的向量化,tez和spark可以支持map和reduce端的向量化操作
复制代码

2. 开启并行化

--开启并行执行
set hive.exec.parallel=true;
复制代码

 ### 3. 开启map端聚合

hive.map.aggr 默认值为true
复制代码

4.调整mapTask数量

set mapred.map.tasks= task数量
复制代码

但是这个并不能完全控制mapTask数量,调节task数量需要一套完整的算法。于mapreduce的切片大小有关。 顾名思义就是将数据进行切分,切分为数据片,其实这个切片关乎于map阶段的map个数,以及每个map处理的数据量的大小。 mapreduce中,一个job的map个数, 每个map处理的数据量是如何决定的呢? 另外每个map又是如何读取输入文件的内容呢? 用户是否可以自己决定输入方式, 决定map个数呢?

mapreduce作业会根据输入目录产生多个map任务, 通过多个map任务并行执行来提高作业运行速度, 但如果map数量过少, 并行量低, 作业执行慢, 如果map数过多, 资源有限,也会增加调度开销. 因此, 根据输入产生合理的map数, 为每个map分配合适的数据量, 能有效的提升资源利用率, 并使作业运行速度加快。

1.默认情况下,Map的个数defaultNum  =目标文件或数据的总大小 totalSize/hdfs 集群文件块的大小blockSize.
2.当用户指定mapred.map.tasks,即为用户期望的Map大小,用expNum表示,但是这个值并不
    会被立即采纳。他会获取mapred.map.tasks与defaultNum的较大值,作为待定选项。
3.获取文件分片的大小和分片个数,分片大小参数为 mapred.min.split.size 和blockSize间的较大值,
    用splitMaxSize表示,将目标文件或数据总大小除以splitMaxSize 即为真是分片个数,用realSplitNum表示。
4.获取realSplitNum于expMaxNum 较小值为实际的Map个数。
复制代码

通过上面的逻辑:

减少Map个数,需要增大mapred.min.split.size的值,减少mapred.map.tasks的值
增大Map个数,需要减少mapred.min.split.size的值,增大mapred.map.tasks的值
复制代码

在之前的学习的union all案例中,单纯的减少,增大map.tasks的数量,并不能改变map个数,读者可以自行尝试。

5.调整reduce相关配置

mapred.reduce.tasks 默认值为-1,代表有系统根据需要自行决定reducer的数量
复制代码

6. 设置每个reducer能处理的数据量

hive.exec.reducers.bytes.per.reducer  设置每个reducer处理的处理量,默认256M
复制代码

7. 表示数据量需要按相同的键再次聚合,可减少重复的聚合操作

hive.optimize.reducededuplication=true;
复制代码

七、使用explain dependency查看数据输入依赖

explain dependency用于描述一段sql需要的数据来源

explain dependency 有两个使用场景

注意在使用join时,不同的join,如inner join left join中有非等值过滤条件,过滤效果不同。

场景一:快速排除 快速排除因为读取不到相应分区的数据而岛主任务数据输出异常,上游任务因为生产过程中不可控因素出现异常或者空跑,导致下游任务引发异常。

场景二:帮助清理表的输入,特别是有助于理解有多重自查询,多表连接的依赖输入。

案例:

下面有两个sql:

select a.s_no 
from student_orc_partition a
inner join student_orc_partition_only b
on a.s_no=b.s_no and a.part=b.part and a.part>=1 and b.part<=2;
复制代码
select a.s_no 
from student_orc_partition a
inner join student_orc_partition_only b
on a.s_no=b.s_no and a.part = b.part
where a.part>=1 and b.part<=2;
复制代码

通过explain dependency,其实上述的两个sql并不等价,在内连接中连接条件中假如非等值的过滤条件后,并没有将内连接的左右两个表按照过滤条件进行过滤,内连接在执行过程中会多读取part=0的分区数据

案例二:

select a.s_no 
from student_orc_partition a
leftjoin student_orc_partition_only b
on a.s_no=b.s_no and a.part=b.part and a.part>=1 and b.part<=2; 
复制代码
select a.s_no 
from student_orc_partition a
leftjoin student_orc_partition_only b
on a.s_no=b.s_no and a.part=b.part and a.part>=1 and a.part<=2; 
复制代码

通过expalin dependency,对于左外连接在连接条件中加入非等值过滤的条件,如果过滤条件是作用于右表(b表)有起到过滤效果,右表只扫描了2个分区,但是左表(a表)会进行全表扫描,

如果过滤条件是针对的是左表,则完全没有起到过滤的作用,那么两个表将会进行全表扫描。

所以通常的优化的是尽早过滤掉不需要的数据。

select a.s_no
from (
select s_no,part from student_orc_partiton
where part>=1 and part<=2
) a
left outer join student_orc_partition_only b
on a.s_no=b.s_no and a.part = b.part;    
复制代码

八、Map join的原理

一般的join 都是Repartition Join,发生在shuffle 和Reduce 阶段,如果不特殊声明,就是Repartition Join。

Map join是先启动一个作业,读取小表的数据,在内存中构建哈希表,将哈希表写入本地磁盘,然后将哈希表上传到HDFS上并添加到分布式缓存中,再启动一个任务读取表B的数据,在进行连接时Map对获取缓存中的数据并存入到哈希表中,B表会与哈希表的数据进行匹配,时间复杂度是O(1),匹配完后将结果进行输出。

一般不建议使用 hinit /*+mapjoin(b) */ 这样的用法,最坏的情况下容易发生内存溢出问题。

可以使用配置来尝试将repartition连接转化为Map连接,hive.smalltable.filesize

桶的Map 连接将普通的Map连接转化为桶连接,分桶的Hive表会将桶列的值计算Hash值取桶数的模,余数相同会发往相同的桶,每个桶对应一个文件。在两表进行连接的时候,可以快速过滤掉不要的数据,

注意使用 桶的map连接要保证连接的两张表的分桶数之前是倍数关系。

九、Skew Join倾斜连接

当有数据倾斜时的表连接。出现数据倾斜时,会引起个别任务花费大量时间和资源在处理倾斜键的数据,从而变为整个作业的瓶颈。Skew Join在工作是会将数据分为两部分,一部分为倾斜键数据,一部分是余下的所有的数据,由两个作业分别处理。

set hive.optimize.skewjoin = true;
复制代码

十、ORC与hive相关配置

orc.compress 表示orc的文件压缩类型,可选类型有NONE,ZLIB,SNAPPY

orc.bloom.filter.columns 需要创建布隆过滤的组

orc.bloom.filter.fpp 使用布隆过滤器的假正概率 默认0.05

hive中使用bloom过滤器,可以用较少的文件空间快速判定数据是否存在于表中

十一、数据倾斜

现象就是任务需要处理大量相同键的数据,这种情况有以下4中表现:

  • 数据含有大量无意义的数据,如空值(NULL)、空字符串
  • 含有倾斜数据在进行聚合计算时,无法聚合中间结果,大量数据都需要经过Shuffle阶段的处理,引起数据倾斜
  • 数据在计算时做多维数据集合,导致维度膨胀引起的数据倾斜
  • 两表进行join,都含有大量相同的倾斜数据键

1. 不可拆分大文件引发的数据倾斜

当对文件使用Gzip压缩等不支持分拣分割操作的压缩方式,当以后有作业读取压缩文件时,改文件只会被一个任务所读取,如果该压缩文件很大,则该map会成为性能瓶颈。

假如一个文件为200M,预先设置每个Map处理数据量为128M,但是计算引擎无法切分这个文件,锁这个文件不会交给两个Map任务去读取,有且只有一个Map任务在操作。

可以采用bzip2和zip等支持文件切分的压缩算法

2. 业务无关的数据引发的数据倾斜

对于空值,NULL这样的,需要在计算过程中排除这些即可。

Solución 1: no participe en la asociación con un user_id vacío

select * from log a join user b on a.user_id is not null and a.user_id = b.user_id
union all
select * from log c where c.user_id is null;
复制代码

Solución 2: Asigne un valor nulo al nuevo valor clave

select * from log a left outer join user b on
case when a.user_id is null then concat('hive',rand()) else a.user_id end = b.user_id
复制代码

Resumir

El método 2 es más eficiente que el método 1. No solo hay menos IO, sino que también la cantidad de trabajos es menor. En el esquema 1, la tabla de registro se lee dos veces y los trabajos deben ser 2, mientras que el esquema 2 es 1. Esta optimización es adecuada para el sesgo de datos generado por identificadores no válidos (como -99, '', nulo) y cambia la clave del valor nulo a

Al agregar un número aleatorio a una cadena , los datos que causan el sesgo de datos se pueden dividir en diferentes reductores para resolver el problema del sesgo de datos.

Cambios: todos los registros que son nulos en sí mismos no se agruparán en la misma reduceTask y se dispersarán en varias reduceTasks debido a valores de cadena aleatorios alternativos. Dado que el valor nulo no está relacionado, no se procesará después del procesamiento. resultado.

1. Sesgo de datos de cálculo de agregación multidimensional causado por la expansión de datos

Para el siguiente escenario, seleccione a,b,c conteo(1) del grupo T por a,b,c con resumen;

Para el sql anterior, se puede dividir en (a,b,c),(a,b,null),(a,null,null),(null,null,null)

Método 1: dividir manualmente este sql

Método 2: puede controlar automáticamente el desmantelamiento de trabajos a través de parámetros. Para operaciones de agregación multidimensional, como conjuntos de agrupación, resumen y cubos, hive.new.job.grouping.cardinality iniciará el mensaje si la combinación final desmantelada es más grande que la configuración predeterminada Tareas para manejar combinaciones diferentes a este valor

2. Sesgo de datos causado cuando dos tablas de datos de colmena están conectadas

Cuando dos tablas ordinarias realizan una unión de repartición, si la tecla de unión de la tabla está sesgada, la fase de barajado inevitablemente provocará una asimetría de datos.

Por lo general, en este caso, todavía hay dos trabajos habilitados. El primer trabajo procesa los datos sin sesgo, y el segundo trabajo almacena los datos sesgados en la memoria caché distribuida, los asigna al nodo donde se encuentra cada tarea de mapa y completa la operación de unión. en la etapa Mapa Evite la reproducción aleatoria, evitando así la asimetría de datos.

Supongo que te gusta

Origin juejin.im/post/7102304965552504869
Recomendado
Clasificación