• 产品与解决方案
  • 行业解决方案
  • 服务
  • 支持
  • 合作伙伴
  • 关于我们

H3C SeaSQL EDW 最佳实践-5W101

01-正文

本章节下载  (1.08 MB)

01-正文

  录

1 最佳实践摘要

1.1 概述

1.2 数据模型

1.3 硬件资源与集群规模

1.4 应用场景

1.5 数据编码与压缩

1.6 数据分段和分区

1.7 Projection

1.7.1 Projection类型

1.7.2 Projection segmentation

1.8 混合负载和工作负载管理

1.9 ANALYZE

1.10 TM(Tuple Mover)

1.11 数据加载

1.12 数据重分布

2 模式设计

2.1 数据类型选取原则

2.2 排序顺序原则

2.3 数据编码与压缩原则

2.4 分布键选择原则

2.5 分区

2.6 存储过程

3 采用资源池管理内存和资源

3.1 内置资源池

3.2 配置自定义资源池

3.2.1 资源分配和调度

3.2.2 并发控制

3.2.3 动态资源管理

3.2.4 常见并发场景优化方法

3.3 实现多租户资源隔离

3.3.1 示例1:管理高优先级查询

3.3.2 示例2:为批量加载分配资源

3.4 资源管理相关的视图

4 系统监控和维护

4.1 概述

4.1.1 MC监控

4.1.2 最佳实践

4.2 更新统计信息

4.2.2 有选择地生成统计信息

4.2.3 提升统计信息质量

4.2.4 何时更新统计信息

4.3 purge和TM操作

4.3.1 purge

4.3.2 TM操作

5 装载数据

5.1 带列值的INSERT语句

5.2 COPY语句

5.2.1 普通copy

5.3 kafka入库

5.3.1 使用copy加载kafka数据

5.3.2 使用调度器加载kafka数据

5.4 最佳实践

6 SQL查询调优

6.1 如何生成执行计划

6.2 如何阅读执行计划

6.3 优化查询方法

6.3.1 整体优化方法

6.3.2 优化Join操作

6.3.3 优化Group by操作

6.3.4 其他

7 高可用性

7.1 磁盘存储

7.1.1 最佳实践

7.2 数据库高可用性

7.3 双集群

7.3.1 最佳实践

7.4 备份和恢复

7.4.1 最佳实践


1 最佳实践摘要

1.1  概述

本文介绍H3C DataEngine MPP数据库(以下简称:DataEngine MPP数据库)的最佳实践。

最佳实践是指能持续产生比其他方法更好结果的方法或者技术,它来自于实战经验,并被证实了遵循这些方法可以获得可靠的预期结果。本最佳实践旨在通过利用所有可能的知识和技术为正确使用DataEngine MPP提供有效参考。

本文旨在帮助用户了解在设计、实现和使用DataEngine MPP数据库时需要遵循哪些最佳实践。关于DataEngine MPP数据库的特性功能介绍及具体使用方法请参考H3C DataEngine MPP用户手册。

本文目的不是要涵盖整个产品或者产品特性,而是概述DataEngine实践中最重要的因素。本文不涉及DataEngine MPP具体特性的边缘用例。

通过掌握这些最佳实践知识,可增加DataEngine MPP集群在维护、支持、性能和可扩展性等方面的操作成功率。

1.2  数据模型

DataEngine MPP数据库时采用无共享的MPP结构,拥有高可扩展性。DataEngine MPP集群中的所有节点100%对等,集群中没有主节点或者其他共享资源。而且是个真正的列式数据库,还会主动地根据列数据的特点和查询的要求选取最佳的算法对数据进行排序和压缩。压缩过的列数据在DataEngine MPP的执行引擎中进行过滤、关联、分组等操作时不需要解压缩,从而大大降低了CPU和内存消耗。

1.3  硬件资源与集群规模

为达到更高的性能,硬件资源对DataEngine MPP非常重要,但为了做到投入和性能的均衡,当进行集群规划时,考虑以下因素:

·     数据量

首先,查看要为集群规划的总的原始数据量,然后应用合理的压缩比。在未使用压缩的情况下,需要具备两倍的原始数据;如果大表使用压缩存储方式,若想计算得到一个更精确的压缩率,请尝试以下方法之一:

¡     使用之前的经验值。

¡     在现有系统上安装DataEngine MPP,导入一部分数据(约10%即可),确保导入的数据能够很好的代表所有数据。导入数据后,通过计算原有数据量大小及实际存储大小,得到一个压缩比。

·     数据增长

请根据实际的数据增长速率(比如每天产生多大数据量)和数据的保留策略(数据库中会保留多长时间的数据)来进行集群的配置设计。

·     负载

考虑以下两方面:

¡     查询的并发量:并发量越大,需要越多的内存。

¡     查询将运行的平均数据量。

说明

·     表1-1中的服务器配置建议是基于2:1的压缩比来进行的,若有更好的压缩比,可以相应的减少节点数目。

·     为获得更好的数据库性能,建议使用的最小内存为256G。

 

表1-1 服务器配置建议

节点类型

服务器硬件要求

管理节点

·     CPU:2路10核,推荐5115(注意:为提高整个集群的性能,应尽量使用主频高性能好的CPU)

·     内存:256GB

·     硬盘:2块600GB SAS硬盘,不少于6块1.2T SAS硬盘

·     RAID卡:1GB Raid0/5卡(带超级电容)

·     网口:2个千兆网口,2个万兆网口

MPP2 Server节点

·     CPU:2路10核,推荐5115

·     内存:256GB

·     硬盘:2块600GB SAS硬盘、不少于12块1.2TB SAS硬盘(注意:硬盘总量相同时,建议使用更多块硬盘)

·     RAID卡:1GB Raid0/5卡(带超级电容)

·     网口:2个千兆网口,2个万兆网口

 

1.4  应用场景

·     OLAP

DataEngine MPP主要应用于AP分析型场景,对报表分析、未来预测等相关复杂查询有优异的表现。执行引擎和优化器基于列式数据库设计的。

·     实时分析

通过内存与磁盘混合存储架构,以及原生支持kafka消息系统的连接,支持数据实时装载分析。

·     应用架构 

一般情况下,DataEngine MPP的在解决方案中处于数据分析角色。

1.5  数据编码与压缩

DataEngine MPP使用编码和压缩来优化查询性能并节省存储空间。

·     编码将数据转换为标准格式,并提高性能。它还将编码值传递给其他操作,从而节省了内存带宽。DataEngine MPP根据数据类型、表基数和排序顺序使用几种编码策略。DataEngine MPP可以直接处理编码数据。运行数据库设计器可以为表提供最佳编码压缩格式。数据库设计器分析表中每一列的数据,并针对每一列的类型进行编码。

·     压缩将数据转换为紧凑格式。DataEngine MPP将整数打包用于未编码的整数,将LZO用于压缩数据。DataEngine MPP数据库在处理压缩数据之前需要对其进行解压缩。

列存储压缩比行存储用更少的存储。在列存储中,存储在projection中的列的每个值都具有相同的数据类型。这极大地促进了压缩,尤其在分类列中。

1.6  数据分段和分区

·     分段是在集群节点之间组织和分发数据,以实现快速数据清除和查询性能。分段旨在在多个数据库节点之间平均分配数据,以便所有节点都参与查询执行。通常情况下,我们会使用create projection语句对大型事实表创建分段projection,数据库将分段的projection分割成相似大小的段,并将这些均匀地分布在整个集群中。

·     分区指定了如何组织单个节点内的数据以进行分布式计算。节点分区使用户可以轻松识别要删除的数据,并帮助回收磁盘空间。用户可以使用create table语句的partition by 子句指定分区。

例如:按年份划分数据对于保留和删除年度数据很有意义。但是,按年份对相同数据进行细分将效率不高,因为持有本年度数据的节点可能比其他节点业务查询要多的多。下图说明了四节点数据库集群上的分段和分区流程:

(1)     表格数据

(2)     数据分布设置HASH(order_id)

(3)     四个节点hash分段情况

(4)     数据按年份在单节点上分区。

图1-1 四节点数据库集群上的分段和分区流程

 

1.7  Projection

与传统数据库数据存储结构不同的是DataEngine MPP将表数据直接存储在projection中。projection是表列的集合,以优化查询执行的格式存储数据,类似于物化视图,projection结果集存储在磁盘上,而不是每次在查询中使用他们时对其进行计算。

Projection具有以下特点:

·     对数据进行编码和压缩以减少存储空间。

·     根据表的大小可以在集群节点之间对projection进行分段或者复制。

·     DataEngine MPP的查询优化器会自动选择最佳的projection给定查询SQL。

·     为数据库提供高可用性。在集群节点发生故障时,可使用其他正常节点数据维持数据库正常运行。

1.7.1  Projection类型

数据库中可存在以下几个projection类型:

·     Super projections

·     Query-specific projections

·     Aggregate projections

·     Buddy projection

1. Superprojections

对于数据库中的每个表,DataEngine MPP至少需要一个包含表中所有列的superprojections。该projection可以支持任何查询和DML操作。

在某些条件下,DataEngine MPP会创建表后立即自动创建表的superprojection。如果未创建super projection,则第一次将数据加载至该表中会自动创建一个superprojection。

2. Query-specific projections

特定于查询的projection是仅包含表列子集的projection。用于处理给定查询以进行优化了那些查询的性能。

3. Aggregate projections

包含表达式或者聚合函数(SUM、count等)的查询在使用已经包含聚合数据的projection时可以更有效地执行。

DataEngine MPP提供以下几种表达式或者聚合函数返回的projection:

·     Live aggregate projection

·     Top-K projection

·     Projection that contains expression

·     Projection that pre-aggregates UDTF results

4. Buddy projection

在数据库K为1或者2时,每个projection都有一个Buddy projection用于维护数据库高可用。

1.7.2  Projection segmentation

1. Segmented projection

通常为大型事实表创建分段projection。将分段的projection分割成相似大小的块,并将这些段均匀地分布在整个集群中。

分段Projection可以实现以下目标:

·     确保高可用性和恢复。

·     将查询执行工作负载分布在多个节点上。

·     允许针对不同的查询工作负载优化节点查询性能。

2. Unsegmented projection

针对维度表相对较小,因此无需对数据进行分段,每个节点上均存储了一份数据。

1.8  混合负载和工作负载管理

DataEngine MPP数据库除了支持对同一表同时进行数据实时加载和分析查询的实时分析外,还提供完善的负载管理机制,保证多个不同负载有效并发执行。

DataEngine MPP内置资源管理,可以管理和调度任务的内存分配、执行并发度、优先级及超时时间的策略,优化资源分配。同时通过资源池划分隔离在线分析查询、批量任务和即系查询等不同任务类型,并支持自动动态管理,确保不同用户及其请求的不同类型的任务都可以满足服务要求。

1.9  ANALYZE

DataEngine MPP数据库中,查询优化器依赖于数据的统计生成查询计划。如果统计信息不完整或者过时,则优化器可能会使用次优计划来执行查询。

DataEngine MPP提供两个功能来生成有关表数据的最新统计信息:

·     ANALYZE_STATISTICS从存储目标表的所有节点收集和汇总数据样本和存储信息。

·     ANALYZE_STATISTICS_PARTITION收集并汇总指定表中一系列分区的数据样本和存储信息。

ANALYZE_STATISTICSANALYZE_STATISTICS_PARTITION分别收集表级别和分区级别的统计信息,DataEngine MPP会将收集的统计信息写入数据库catalog目录。

1.10  TM(Tuple Mover)

DataEngine MPP提供了数据存储选项,将大数据文件批量加载至文件系统中称为ROS。ROS中的数据为已排序、编码和压缩的数据。

Tuple Mover是DataEngine MPP的一个服务,在后台运行并负责管理ROS数据存储。

Mergeout是一个TM的进程,用于合并ros container并清除已删除的记录。DML活动例如加载数据和数据分区会生成新的需要合并的ros container,而删除和重新分区数据则需要对现有的ros container进行重组。

1.11  数据加载

DataEngine MPP提供了多种读取数据的方法。

·     从多种源头将数据加载至数据库中

·     使用外部表的原始格式就地读取数据

·     使用数据流传输

·     从其他DataEngine MPP数据库导入数据

数据库中大多数据数据加载操作都围绕着copy语句,默认情况下,copy会自动提交自身以及任何当前事务,除非加载的是临时表。如果copy终止或者中断,DataEngine MPP会将其回滚。

默认情况下,copy以UTF-8编码格式读取数据。支持以下几种加载方式:

·     从文件中加载数据

数据加载中可能有很多文件在共享存储或者本地节点上,可以采用直接加载本地数据文件。支持csv、parquet、json等格式数据直接加载。

·     从其他服务加载数据

¡     Kafka是流数据的服务平台,DataEngine MPP支持处理kafka的数据流。

¡     Hdfs是分布式数据的存储框架,DataEngine MPP支持链接到hdfs获取数据。

¡     也可以直接从另一个DataEngine MPP集群中复制数据,而不需要将数据导出成文件再加载。

·     直接读取外部文件数据(不导入)

无需将数据加载至DataEngine MPP中,可以使用外部表的形式读取数据。

有时候会存在数据不干净,数据可能与数据类型不匹配,或者缺少必要的值,或者解析器由于其他原因无法解析数据。用户可以在copy语句的参数指定容错程度以及在何处记录有关拒绝数据的信息。

1.12  数据重分布

在集群进行扩容或者缩容时,DataEngine MPP需要对数据进行重新均衡分布。作为超级用户,可以使用管理工具,SQL函数或者管理控制台手动触发重新均衡。如下,以下操作后需要进行数据重新均衡:

·     通过添加或者删除节点来更改集群的大小。

·     将一个或者多个节点标记为临时节点,以准备将其从集群中删除。

·     在大集群布局上设置控制节点大小或重新排列控制节点。

·     在初始集群配置中指定超过120个节点。

·     通过添加或者删除节点修改故障组。

在重新数据均衡之前,DataEngine MPP将以现有的K-safety值运行。重新均衡完成后,DataEngine MPP将以重新均衡操作期间指定的K值运行。新的k值必须等于或者大于当前K值。DataEngine MPP不支持降级K-safety,否则会返回警告。

 


2 模式设计

2.1  数据类型选取原则

表间连接中用到的列必须使用相同的数据类型。如果数据类型不同,DataEngine MPP数据库会动态地转换其中一列的数据类型,以正确地比较数据值。

·     使用最小空间的数据类型

·     通过选择最有效的数据类型存储数据,可以增加数据库容量和改进查询执行效率。

¡     使用VARCHAR而不是CHAR,降低使用的存储空间。

¡     使用能容纳数据的最小数字数据类型,可以节省存储空间。例如,对于适合于INT或SMALLINT的数据,不要使用BIGINT。

2.2  排序顺序原则

DataEngine MPP数据库中projection里面的列的排序顺序往往决定了表的压缩率、sql的查询性能等。一般如果查询列是低基数列,那么使用RLE和Sort能有效提升查询性能和提高压缩比。基数越高压缩率越低,列的长度越长压缩比越高。为了能够最大限度的提升RLE的效率,应只在列的平均run length大于10且排序的时候使用RLE。另外还有以下需要注意的优化项:

·     查询相关的列,把基数低的列放前面。

·     合理的选择 merge join或者hash join,当对象已经排序时 merge join由于不需要预处理,性能优,而如果对象无序且是小表可以完全放入内存做处理时,hash join性能更优。

·     对于重要的SQL语句,如果列基数比较高,需要牺牲部分存储换取SQL性能的优化。

·     如果有两列基数相同,那么把列长度长的放在前面,压缩比会更高。

·     把关联或者分组用的列放在排序第一位。

·     等值过滤条件优先放在排序第一位,不影响后续列的有序性。

·     Delete/Update/Merge的条件列包含在排序中(可以放在末尾),以提高删除和复原时的查找速度。

2.3  数据编码与压缩原则

DataEngine MPP使用编码和压缩来优化查询性能并节省存储空间。

·     编码是将数据转换为标准格式。

DataEngine MPP可以直接处理编码的数据,查询处理器尽可能使用编码数据以避免解码过程,它同时会把编码数据传递给其他操作。数据库根据数据类型、表基数和排序顺序使用集中编码策略。

·     压缩是将数据转换为紧凑格式。

DataEngine MPP将整数打包用于未编码的整数,将LZO用于压缩数据。在处理压缩数据之前,必须先对其进行解压缩。

DataEngine MPP支持12种由encoding参数指定的编码压缩算法。不同的列,根据其数据类型及实际数据,选择不同的压缩算法,能够获得一个更好的压缩比。

表2-1 编码压缩算法说明

算法名称

说明

RLE

RLE(run length encoding)将相同值的序列替换为包含值和出现次数的单个对。最适合应用于projection的order by子句中的低基数列。

BLOCK_DICT

对于每个存储块,DataEngine MPP将不同的列值编译成一个字典,然后存储字典和一个索引列表来表示数据块。

BLOCK_DICT非常适合于少值、未排序的列,在这些列中,节省空间比编码速度更重要。

BLOCKDICT_COMP

这种压缩类型与BLOCK_DICT类似,只是字典索引是熵编码的。这种压缩类型需要更多的CPU时间来编码和解码,并且在最坏情况下的性能较差。然而,如果值的分布极为倾斜,则使用BLOCK_DICT_COMP编码可以节省空间。

DELTAVAL

对于整数和日期/时间/时间戳/间隔列,数据记录为与数据块中最小值的差值。这种编码对其他数据类型不起作用。

DELTAVAL最适合用于多值、未排序的整数或基于整数的列。这种编码类型对CPU的要求很低,数据永远不会扩展。

COMMONDELTA_COMP

这种压缩方案建立一个包含块中所有增量的字典,然后使用熵编码将索引存储到增量字典中。

此方案适用于具有可预测序列且仅偶尔出现序列中断(例如以周期间隔或主键记录的时间戳)的排序浮点和基于整数(日期/时间/时间戳/间隔)的数据列。

DELTARANGE_COMP

这种压缩方案主要用于浮点数据,它将每个值存储为前一个值的增量。

此方案适用于排序或限制在某个范围内的多值浮点列。不要对包含空值的未排序列使用此方案,因为表示空值的存储成本很高。

GCDDELTA

对于整数和日期/时间/时间戳/间隔列,以及18位或更少数字的数字列,数据记录为数据块中最小值除以块中所有项的最大公约数(GCD)的差值。当值是公共因子的倍数时, GCDDELTA最好用于多值、未排序、整数列或基于整数的列。

BZIP_COMP

BZIP_COMP压缩对块内容使用bzip2压缩算法。该算法比自动LZO和gzip编码具有更高的压缩率;然而,它需要更多的CPU时间来压缩。该算法最适合用于大型字符串列,如VARCHAR、VARBINARY、CHAR和BINARY。当用户愿意用较慢的加载速度换取较高的数据压缩时,请选择这种编码类型。

GZIP_COMP

这种编码类型使用gzip压缩算法。该算法的压缩效果优于自动LZO压缩,但压缩效果低于BZIP_COMP。它比LZO需要更多的CPU时间进行压缩,但比BZIP_COMP需要更少的CPU时间。该算法最适合用于大型字符串列,如VARCHAR、VARBINARY、CHAR和BINARY。当用户想要比LZO更好的压缩,但比bzip2占用更少的CPU时间时,可以使用这种编码。

ZSTD_COMP

ZSTD_COMP提供高压缩比。这种压缩类型要比gzip的压缩比高。当你想要获取比gzip更好的压缩时,可以使用这个选项。对于一般用例列,使用该压缩方法或ZSTD_FAST_COMP压缩方法。

ZSTD_FAST_COMP

ZSTD_FAST_COMP使用ZSTD库提供的最快压缩级别。它是zstd库中最快的压缩类型,但比其他两种编码类型占用更多空间。对于一般用例列,使用该压缩方法或ZSTD_COMP压缩方法。

ZSTD_HIGH_COMP

ZSTD_HIGH_COMP提供了ZSTD库中最好的压缩。它比其他两种编码类型慢。在需要最佳压缩且CPU时间较慢时使用此类型。

 

说明

如果没有指定编码或者压缩,将使用AUTO作为默认值。AUTO编码非常适合用于排序的多值列,例如主键。它也适用于没有其他编码或压缩方案的通用应用。

 

合理的列编码格式能够降低数据磁盘存储大小以提升查询的效率,可根据数据类型及数据基数选择不同的编码压缩算法,如表2-2所示。

表2-2 编码与压缩原则

编码类型

数据类型

基数

排序

BLOCK_DICT

Compile sand creates pointers to distinct column values

CHAR(short)

VARCHAR(short)

DELTARANGE_COMP

Stores each value as a delta from the previous value

FLOAT

DELTAVAL

Stores each value as a delta from the smallest value

INTEGER

DATE

TIME

TIMESTAMP

INTERVAL

RLE

Replaces runs of identical values with a value/counter pair

CHAR

VARCHAR

NUMERIC

2.4  分布键选择原则

·     尽量选择经常需要JOIN的列。

·     当关联键和分布键一致时,可以在相对应的节点中完成JOIN,不需要重分布或者广播小表。

·     当关联键和分布键不一致时,则需要重分布不一致的表或者广播小表,会带来额外的开销。除此之外,group by、window function会造成数据重分布。

·     尽量选择分布均匀的列或者多列,若选择的分布列值分布不均匀,可能会导致数据倾斜。实际应用中,如果单列不能达到分布均匀的时候建议选用多列进行联合分布,以达到均匀分布的目的。

·     尽量选择高并发查询的条件列。如果数据经常被高并发的键值或离散查询,可以将查询条件的列作为分布列,这样不需要连接和查询所有的节点,可以大大提高并发能力。

2.5  分区

1. 分区和ROS container

默认情况下,DataEngine MPP支持最多1024个ros container来存储数据。ros container包含相同分区键或者相同分区组键的数据。根据每个分区的数据量,一个分区或者分区组可以跨越多个ros container。

建议一个表中分区数不要超过1024个,否则会出现ros回退的告警,并拒绝加载更多数据。

2. 分区类型

·     只分区大型表,不要分区小型表。

·     不要在相同的列做表分区和分布。

·     根据数据合理设置分区,分区个数不得超过1024。建议每张表分区数不超过50。

·     针对热数据与冷数据可采用分层分区。

·     建议按照时间进行分区。

2.6  存储过程

许多其他数据库针对在线事务处理(OLTP)进行了优化,OLTP侧重于频繁的事务。相比之下,DataEngine MPP针对在线分析处理(OLAP)进行了优化,OLAP专注于存储和分析大量数据,并对这些数据上最复杂的查询提供最快的响应。

这种架构差异意味着DataEngine MPP中存储过程的推荐用例和最佳实践与其他数据库中的存储过程略有不同。

虽然面向OLTP的数据库中的存储过程通常用于执行小型事务,但应使用面向OLAP的数据库(如DataEngine MPP)中的存储过程来增强分析工作负载。DataEngine MPP可以处理孤立的事务,但频繁的小型事务可能会影响性能。

对于DataEngine MPP中的存储过程,包括信息生命周期管理(ILM)活动,如提取、转换和加载(ETL),以及为机器学习等任务准备数据。例如:

·     根据使用年限交换分区

·     在生命周期结束时导出数据并删除分区

·     保存机器学习模型的输入、输出和元数据运行模型的人、模型的版本、模型的运行次数以及谁收到结果

DataEngine MPP中的存储过程还可以对需要比调用方更高权限的对象进行操作。


3 采用资源池管理内存和资源

DataEngine MPP通过资源池对系统进行资源管理。资源池可以分为内置(系统)资源池和用户自定义资源池两种。资源池用于资源的分配和调度、并发控制、动态资源管理。

3.1  内置资源池

DataEngine MPP有以下内置资源池:

表3-1 内置资源池及设置

资源池名称

描述

general

系统默认资源池,对于没有指定资源池的用户操作,默认使用该资源池资源

blobdata

控制内存中blob的资源使用

dbd

控制数据库优化设计(DBD)进程的资源使用

jvm

控制用户自定义Java扩展使用的Java虚拟机资源

metadata

跟踪分配给catalog数据的内存资源

recovery

节点发生故障,进行恢复时使用的资源池

refresh

刷新新增projection时使用的资源池

sysquery

对系统表进行查询时使用的资源池

tm

控制与Tuple Mover相关的查询的资源使用

 

可以使用系统表resource_pools查看DataEngine MPP所有的资源池大小,也可以通过resource_pool_status查看源池的使用情况。

3.2  配置自定义资源池

可以使用自定义的资源池补充内置资源池,以处理特定的数据库的需求。如果跨不同类别的工作负载具有竞争资源要求,则用户定义的资源池非常有用。

使用用户定义的资源池,可以:

·     处理数据加载类工作

·     限制内存使用,并发和优先级

·     将用户限制为特定资源池

可以使用create resource pool语句创建自定义资源池,对于资源池的以下各个参数,其作用如表3-2所示。

表3-2 资源池参数描述

参数

默认值

描述

executionparallelism

AUTO

每个任务执行并行度(线程数),缺省为AUTO

cpuaffinityset

none

运行的CPU核集合,缺省为空

cpuaffinitymode

ANY

CPU粘连模式,缺省为ANY

memorysize

0%

保留的专用内存,为0表示可以从GENERAL借的内存大小没有限制

maxmemorysize

NONE

允许从general使用的最大内存,默认为95%

plannedconcurrency

AUTO

使用该资源池的并发任务期望值,默认为CPU核心数

priority

0

任务排队优先级,取值-100到100

queuetimeout

300

任务排队超时时间(单位为s),会被拒绝。NONE表示永不超时

runtimeprioritythreshold

2

任务以高优先级开始执行的时间,单位为s

runtimepriority

medium

达到阈值后的运行优先级别

runtimecap

none

任务执行时长阈值,执行超时强制进入指定级联资源池,或被中断

cascade to

任务执行时间超过runtimecap后的目标资源池名称。默认为Empty

maxconcurrency

none

最大并发任务数,缺省不限制

 

3.2.1  资源分配和调度

1. CPU分配

·     executionparallelism:每个任务执行的线程数。

·     cpuaffinityset与cpuaffinitymode:高优先级任务可以独占特定的CPU。

2. 内存分配

·     memorysize:独占的内存。就算空闲,别的资源也不能使用。

·     maxmemorysize:允许使用的最大内存。申请内存超出该值后任务会被立即拒绝。资源池已用内存达到该值后,后续任务会排队。

·     任务内存预算:query_budget=maxmemorysize/plannedconcurrency。

说明

预算的含义:规划的时候为任务预留,多退少补。但如果资源池剩余内存不够下一个任务的预算,该任务会被排队。

 

3. 排队和优先级

·     资源(内存和CPU)不满足任务的请求,任务就会被排队。

·     优先级priority高的队列,会优先申请到内存。

3.2.2  并发控制

1. 直接限制

最大并发数maxconcurrency,资源池中正在执行的任务数达到maxconcurrency后,后续的任务排队。

2. 间接限制

资源不足

·     资源池已用总内存达到maxmemorysize后,后续任务排队。

·     可以粗略的认为:资源池并行任务执行数<=plannedconcurrency。

3.2.3  动态资源管理

1. 运行时动态调整

·     任何任务都会按最高优先级执行runtimeprioritythreshold时长,然后再按runtimepriority优先级执行。

·     任务执行时间超过runtimecap后,会被中断执行,或者进入指定级联资源池。

2. 资源池级联

任务执行时间超过runtimecap后,会被移动到cascadeto指定的资源池继续执行(如果新资源池有足够资源)或重新排队。

3.2.4  常见并发场景优化方法

并发(混合负载)优化是个统筹优化问题,应先设置目标和评价方法。

1. 基本原则

·     应用层要求通过连接池等技术控制并发请求,数据库上的并发请求通常不宜比CPU核数高太多,因为每个连接(哪怕是空闲的)都要消耗一个线程

·     业务用户一定要有自己的资源池,杜绝用缺省general pool,否则系统过载时,数据库管理员用户的管理任务也得排队

·     用profile来评估查询的内存需求,通常让query_budget刚刚满足需求即可,这样可以同时执行更多的任务

2. 特定应用的性能要求高

·     给它高优先级(priority)以便更快抢到资源

·     运行优先级(runtimepriority)为high

·     甚至独占CPU(cpuaffinity*)和内存(memorysize)

3. 特定应用并发/吞吐量要求高

·     尽量用merge join/group by pipe替代hash join、group by hash,尽管单个查询hashjoin/grouphash可能会更快,但它消耗更多的CPU和内存,不利于并发。

·     降低高并发时的上下文切换导致的竞争。高并发场景(尤其是小查询)应适当降低执行并行度(executionparallelism),以避免过高的context switch和系统调用CPU开销。

·     给较多的并发数(maxconcurrency)和最大内存(maxmemorysize)。

4. 实在无法对负载进行直接区分,但需要更高的吞吐能力

采用资源池级联,让长时间任务在跟低并发的资源池排队,避免“入口”资源池排队,给新进来的小任务执行机会。

3.3  实现多租户资源隔离

通过创建资源池,分配特定的资源,进而将资源池和用户绑定,使得该资源池资源满足用户的特定需求。对于多租户场景,可以通过为不同租户绑定不同资源池,实现租户间的资源隔离。

3.3.1  示例1:管理高优先级查询

1. 获取特定业务所需资源

想象一下,用户的企业CEO经常通过第三方BI工具运行以下查询:

=> SELECT DISTINCT s.product_key, p.product_description

FROM store.store_sales_fact s, public.product_dimension p

WHERE s.product_key = p.product_key AND s.product_version = p.product_version

AND s.store_key IN (SELECT store_key FROM store.store_dimension WHERE store_state = 'MA')

ORDER BY s.product_key;

现在你希望确保查询始终具有要运行的资源,而不用和其他用户查询共享general资源池,因为这样有可能会导致查询排队或超时。

那么你需要执行以下步骤:

(1)     通过profile命令获取查询所需的内存资源大小:

=> PROFILE SELECT DISTINCT s.product_key, p.product_description

FROM store.store_sales_fact s, public.product_dimension p

WHERE s.product_key = p.product_key AND s.product_version = p.product_version

AND s.store_key IN (SELECT store_key FROM store.store_dimension WHERE store_state = 'MA')

ORDER BY s.product_key;

NOTICE 4788:  Statement is being profiled

HINT:  Select * from v_monitor.execution_engine_profiles where transaction_id=45035996274783380 and statement_id=1;

NOTICE 3557:  Initiator memory for query: [on pool general: 693504 KB, minimum: 640011 KB]

product_key |          product_description

-------------+----------------------------------------

1 | Brand #1 butter

1 | Brand #2 bagels

(2)     查询返回一个提示并估计查询所需的内存量。从提示中复制事务和语句ID,并在以下查询中使用它们来确认查询实际使用了多少内存:

=> SELECT MAX (memory_kb) memory_kb FROM dc_resource_acquisitions WHERE transaction_id = 45035996274783380 AND statement_id = 1;

memory_kb

-----------

696213

(1 row)

(3)     可以获取到,该查询所需要的内存约为696213KB。

2. 创建资源池

使用数据库管理员创建至少满足查询内存使用量的资源池:

CREATE RESOURCE POOL ceo_pool MEMORYSIZE '700000K';

3. 授予用户资源池使用权限

授予用户ceo资源池ceo_pool的使用权限:

GRANT USAGE ON RESOURCE POOL ceo_pool TO ceo;

4. 关联用户与资源池

ALTER USER ceo RESOURCE POOL ceo_pool;

将用户ceo与资源池ceo_pool关联后,为该池分配的资源仅为该用户的查询保留。如果需要,用户可以将此资源池的使用扩展到其他用户或角色。

3.3.2  示例2:为批量加载分配资源

批量加载通常比常规查询需要更多的时间和内存。通过将自定义资源池用于批量加载,general资源池可以自由处理查询。

1. 创建用户

CREATE USER etluser;

2. 为批量加载创建资源池

CREATE RESOURCE POOL batch_pool MEMORYSIZE '2G' MAXMEMORYSIZE'6G' MAXCONCURRENCY 3;

3. 授予用户资源池使用权限

GRANT USAGE ON RESOURCE POOL batch_pool TO etluser;

4. 关联用户和资源池

ALTER USER etluser RESOURCE POOL batch_pool;

3.4  资源管理相关的视图

DataEngine MPP提供以下系统表,来监控资源池中的资源分配及使用。

表3-3 系统表说明

系统表

描述

RESOURCE_POOLS

所有资源池的参数,包括内置资源池

RESOURCE_REJECTIONS

资源请求拒绝情况和拒绝原因

RESOURCE_ACQUISITIONS

执行过的每个查询资源请求信息

RESOURCE_POOL_STATUS

所有资源池的当前状态,包括内存使用情况、正在执行的并发查询数

RESOURCE_QUEUES

当前等待队列中的查询,保持资源池和优先级信息

USERS

用户关联的资源池信息

 


4 系统监控和维护

4.1  概述

本节介绍日常运维相关的最佳实践,关注这些内容可以确保DataEngine MPP数据库日常高可用性和性能保持最佳状态。

4.1.1  MC监控

DataEngine MPP数据库提供了一个对监控数据库集群非常有用的工具Manage console(MC)。

MC是DataEngine Mpp用来管理集群的一个Web页面,通过JDBC的方式连接到数据库集群,可以对集群系统资源、数据库资源的使用进行实时的监控,也可以对数据库状态、会话连接情况进行查看,此外也可以作为客户端对数据库表进行DDL、DML、查询以及数据导入等操作。

以下内容会对MC常用的、比较重要的使用场景进行介绍。更多的功能,可以在使用中逐步探索。

说明

关于MC的安装及导入数据库操作,请参考H3C DataEngine MPP安装部署手册,在此假设已完成MC的安装与数据库导入操作,且已经进入数据库。

 

1. 监控查询

可通过MC监控用户查询相关的内容及统计。如运行查询数目,查询使用资源池,查询使用内存,查询持续时间等项。如下图所示:

 

2. 监控会话

通过MC可以监控当前数据库的所有会话,并且可以直观的看到当前执行SQL,请求持续时间,并能直接关闭会话。

 

3. 进行数据库优化设计

通过MC,可以很方便的进行数据库优化设计(DBD)。

 

4. 监控数据加载

通过MC可以监控使用kafka加载数据的过程。如显示加载的目标表,加载状态,加载成功的行数和加载失败的行数。

 

5. 查看profile和执行计划信息

可以很直观的看到SQL执行profile时的各阶段耗时,以及具体的资源使用占比。这可以协助分析优化具体SQL。

 

4.1.2  最佳实践

·     通过设置合理的监控阈值,来更好的监控数据库的运行状态。

·     关注“消息中心”的每天的告警信息,检查异常事件并确定原因。

·     按照需求,设置合理的MC用户登录管理级别。

4.2  更新统计信息

良好查询性能的最重要先决条件是从表的正确统计信息开始。用analyze_statistics语句更新统计信息让查询规划器能生成最优的查询计划。当表被分析时,有关数据的信息被存储在系统目录表中。如果存储的信息过时,规划器可能会生成低效的执行计划。

analyze_statistics语句的使用方法为:

select ANALYZE_STATISTICS ('[ scope ]' [, 'column[,…]'] [, percent ] );

其参数为:

表4-1 参数说明

参数

说明

scope

指定具体的表来搜集统计信息,格式为:[[database.]schema.]table

若scope参数为空,将收集数据库中所有表及其projections的统计信息

column

要收集信息的表中的某一列的名称,可以通过‘,’来间隔指定多个列名。DataEngine MPP可以只收集这些指定列的统计信息

precent

一个介于0-100间的浮点值。用于指定从磁盘中读取数据的百分比。默认值为10

设定该值大于10,将延长统计信息收集的时间,但是能够提高统计信息的精确度

 

4.2.2  有选择地生成统计信息

不带参数运行analyze_statistics会为数据库中所有的表更新统计信息。这样操作运行时间可能会非常长,因此不推荐这样做。当数据被改变时,使用者应该有选择地收集表的统计信息。

在大型表上运行analyze_statistics可能需要很长时间。如果在非常大的表的所有列上运行analyze_statistics行不通,使用者可以只使用analyze_statistics(tablename,column_name)为选择的列生成统计信息。确保包括用在连接、WHERE子句、SORT子句、GROUP BY子句或者 HAVING子句中的列都被收集了统计信息。

4.2.3  提升统计信息质量

在生成统计信息所花的时间和统计信息的质量或者准确性之间存在着权衡。

为了允许大型表能在合理的时间内被分析完,analyze_statistics会对表内容做随机采样而不是检查每一行。要对所有表列增加采样,可调整analyze_statistics函数参数中的precent参数。其目标值取值范围从 1到100,默认值是10。

4.2.4  何时更新统计信息

如果满足以下一个或多个条件,则应使用analyze_statistics函数来对表或其中的列收集统计信息:

·     第一次加载数据完成

·     刷新了新的projection

·     表中的行数发生了很大的变化

·     表中新增了列

·     列的最大值/最小值有很大变化

·     当添加了具有参照完整性的新主键值,主键和外键应重新收集统计信息。

·     表大小相对于其他关联的表发生显著变化。

·     数据分布存在显著偏差需要重新计算直方图。

·     数据库长期处于非活动状态

对于许多应用程序,统计数据时不需要精确到最新的时刻。DataEngine MPP会定期调用ANALYZE ROW COUNT(统计表的行数),它会收集部分统计信息并提供足够的数据以满足许多优化程序的要求。

4.3  purge和TM操作

注意

大型删除和清除操作可能需要很长时间才能完成(会锁表),且可能会临时占用大量磁盘空间,因此请谨慎使用。如果用户的应用程序需要定期(例如按月或按年)删除数据,请考虑设计利用分区表。如果分区不合适,请考虑重建表

 

在DataEngine MPP中,数据被delete后,并没有被删除,还存在于历史数据中,历史数据的存在,会占用磁盘空间及影响数据库查询等性能。所以需要进行purge操作。

在DataEngine MPP中,purge操作其实是通过Tuple Mover(TM)中的mergeout操作来进行的,后台会定时执行mergeout操作。

4.3.1  purge

DataEngine MPP的purge策略有两种:

·     设定策略自动清除

·     手动清除

1. 设定策略自动清除

清除数据的首选方法是建立一个策略,该策略确定哪些删除的数据符合清除条件。当Tuple Mover执行合并操作时,将自动清除已标记删除的数据。

DataEngine MPP提供了两种方法来确定何时可以清除已删除的数据:

·     指定删除数据的保存时间

·     指定保存的epoch数

 

指定删除数据的保存时间

指定保存删除数据的时间是确定可以清除哪些删除数据的首选方法。

具体的SQL命令为:ALTER DATABASE mydb SET HistoryRetentionTime = {seconds | -1};

在以上语法中:

·     mydb表示要修改的数据库名称

·     seconds是保存已删除数据的时间(以秒为单位)。

·     -1 表示用户不想使用HistoryRetentionTime 配置参数来确定哪些清除的数据符合清除条件。

 

指定保存的epoch数

除非有理由限制epoch的数量,否则DataEngine MPP建议使用者指定保存删除数据的时间。

(1)     首先关闭HistoryRetentionTime配置参数:

ALTER DATABASE mydb SET HistoryRetentionTime = -1;

(2)     其次通过HistoryRetentionEpochs配置参数设置历史epoch保留级别:

ALTER DATABASE mydb SET HistoryRetentionEpochs = { num_epochs | -1};

¡     mydb表示要修改的数据库名称。

¡     num_epochs是保存的epoch值。

¡     -1表示用户不想使用HistoryRetentionEpochs配置参数来确定哪些清除的数据符合清除条件。

2. 手动清除

DataEngine MPP支持手动清除数据库中所有表、某个表、某个projection,某个partition中被删除的数据。

·     清除数据库中所有表

select purge();

注意:该操作可能会非常耗时,请谨慎操作。

·     清除某个表

select purge_table(‘tablename’);

注意:对于大表,谨慎执行该操作。

·     清除某个projection

select purge_projection(‘projection_name’);

·     清除表的某个分区

select purge_partition(‘tablename’,partition_key);

4.3.2  TM操作

DataEngine MPP带有读优化存储ROS,Tuple Mover(TM)操作就是用于处理这种优化存储的。

函数do_tm_task有一个参数:mergeout,合并ROS容器并清除已删除的记录。

使用方法为:select DO_TM_TASK('mergeout',{table | projection}]')

其参数如表4-2所示。

表4-2 参数说明

参数

说明

task

l     mergeout: 合并ROS容器并清除已删除的记录

l     analyze_row_count:收集指定projection的行数。

l     update_storage_catalog(仅用于EON模式数据库):更新绑定的表的元数据目录

table | projection

表或projection名称

 

1. mergeout操作最佳实践

Tuple Mover的mergeout操作在后台运行并合并ROS容器。每个节点每个projection的最大ROS容器数为1024。如果在数据加载过程中遇到错误,提示“ TOO MANY ROS CONTAINERS”,则每个节点每个projection的最大ROS容器数已达到最大限定值。mergeout将ROS容器合并为更少的容器,从而使数据库在正常使用情况下不会达到此限制。

·     TM资源池的内存大小

如果用户的数据库有宽表(超过100列),请增加TM资源池的memorySize和maxMemorySize,以加快对宽表的操作。

·     表分区

每个表创建50个或更少的分区,因为DataEngine MPP不会跨分区合并ROS容器。因此,具有数百个分区的表可能会很快受到ROS的限制。用户可以使用ALTER TABLE ALTER PARTITION命令更改表的分区方案。

·     配置参数:ActivePartitionCount

如果用户的表频繁接收到当前和最近的非活动分区中的数据,请将ActivePartitionCount参数从默认值1更改为2。DataEngine MPP希望该分区基于时间,其中一个活动分区接收数据,而其他非活动分区很少或从不接收数据。Tuple Mover将非活动分区的ROS容器合并到单个ROS容器中。

·     限制在同一表上的projection集

同一张表上固定的projection集不能超过两个。每个表具有两个以上的projection集会导致系统资源浪费。

·     projection排序顺序准则

排序的列要少于10列,并避免排序包含宽的VARCHAR列。这有助于减少合并操作运行所花费的时间。长时间运行的操作可能会阻塞合并线程,从而增加了ROS容器的数量。

·     批量删除和更新

尽可能批量删除和更新。

·     配置参数: MergeOutInterval

系统执行mergeout操作的时间间隔。该参数的默认值为600(单位s),若ros容器产生过快,可以考虑减小该值。

·     TM资源池的MaxConcurrency和PlannedConcurrency

如果用户考虑了前面列出的最佳实践,但是用户的工作量需要更多的合并线程,请将TM资源池的MaxConcurrency和PlannedConcurrency参数从3增加到4。

【注意】:请勿将此值增加到大于6。

 


5 装载数据

本节描述了将数据装载到数据库的不同方式。

5.1  带列值的INSERT语句

带有值的单个INSERT语句会向表中加入一行。

insert into store values(‘xx1’,’xx2’);

对于insert语句,这是最慢的方法并且不适合装载大量数据。

5.2  COPY语句

DataEngine MPP的COPY语句从外部文件拷贝数据到数据表中。它比INSERT 语句插入多行的效率更高,数据从一个节点入库,然后按照规则均匀分布到所有节点上。所有数据都在一个命令中被拷贝,它并不是一种并行处理。

COPY命令的数据输入来自于一个文件或者标准输入。例如:

COPY sampletab FROM '/home/dbadmin/one.dat' DELIMITER ',' NULL E'\\\N' ;

因为COPY是一个单一命令,在使用这种方法填充表时没有必要禁用自动提交。

使用者可以运行多个并发的COPY命令以提高性能。

5.2.1  普通copy

1. 并行加载

·     DataEngine MPP可以在copy命令中指定一个或多个节点名称及文件,来实现多个数据源的同时加载,如下所示:

COPY schema-name.target-table FROM

'/path/1.dat' ON node0001,

'/path/2.dat' ON node0002,

'/path/3.dat' ON node0003,

'/path/4.dat' ON node0004,

'/path/5.dat' ON node0005 ;

·     如果全部数据只在本地文件系统的某一个节点上或者共享存储(如HDFS)上时,可以使用如下方法:

a.     在集群中建立共享文件系统(NFS),将实际存放数据的节点作为服务器节点,其他节点作为客户端节点。

b.     copy时使用ON ANY NODE命令。指定此子句,COPY将打开该文件并从群集中的任何节点解析该文件。

注意

ON ANY NODE是HDFS和S3路径的默认值。如从共享文件目录加载一些大文件到表:COPY myTable FROM '/data/manyfiles/*.dat' ON ANY NODE;

 

2. 加载数据时的拒绝信息

COPY语句自动将每个被拒绝行的副本保存在被拒绝的数据文件中。 COPY还保存了对异常文件中拒绝原因的相应解释。 默认情况下,DataEngine MPP将这两个文件保存在名为CopyErrorLogs的数据库catalog目录的子目录中,如下所示:

v_mart_node003_catalog\CopyErrorLogs\trans-STDIN-copy-from-rejected-data.1

v_mart_node003_catalog\CopyErrorLogs\trans-STDIN-copy-from-exceptions.1

可以查看这些文件,以确定哪些行加载错误以及可能的错误原因。

5.3  kafka入库

DataEngine MPP提供kafka连接器将数据从Kafka消息总线流式传输到DataEngine MPP数据库,从而简化应用调度实时装载的难度。DataEngine MPP提供自动或者手动使用kafka数据负载工具来进行数据装载。

DataEngine MPP与kafka的集成提供以下功能:

·     提供kafka数据向DataEngine MPP的每个节点并行读取和装载数据的装载函数,支持JSON、Avro 、字符串等多种格式数据秒级延迟的实时装载,装载可达到TB/h。装载的任务借助数据库的事务与kaka的容错机制确保数据只被装载一次。

·     提供可视化的监控工具。

5.3.1  使用copy加载kafka数据

可以使用COPY语句将数据从Kafka手动流式传输到DataEngine MPP。此技术类似于从其他源(例如本地文件系统,客户端系统或HDFS)复制数据。

当要分析一组特定的消息时,从Kafka手动复制数据非常有用。当用户想在配置调度程序之前,进行kafka流式数据加载测试,它也很有用。

与使用调度程序相比,从Kafka手动复制数据还使用户可以更好地控制数据加载。例如,假设用户要在从Kafka加载数据期间执行业务逻辑或自定义拒绝处理。调度程序不支持在其事务期间执行其他处理。而用户可以选择定期运行一个执行COPY语句的事务,以从Kafka加载数据,然后执行其他处理。

与其他复制方法不同,从Kafka复制通常意味着用户的COPY语句将在指定的时间段内加载数据,而不是从文件或其他源中加载所有数据。例如,用户可以选择复制一分钟Kafka中topic的消息。DataEngine MPP仅复制那一分钟内流式传输的数据。持续时间结束后,COPY语句结束,DataEngine MPP不再加载任何其他数据。

5.3.2  使用调度器加载kafka数据

DataEngine MPP提供了一个调度器,用于加载来自一个或多个Kafka主题的流式消息。与手动使用COPY相比,自动加载流数据有许多优点:

·     流数据会自动显示在数据库中。新数据在数据库中出现的频率由调度器的帧持续时间决定。

·     调度器提供恰好一次的消费过程。调度器管理偏移量,以便Kafka发送的每条消息都被消耗一次。

·     调度器管理数据加载的资源。可以通过设置分配给它的资源池来控制其资源使用情况。而手动加载时,每次必须考虑负载消耗的资源。

5.4  最佳实践

·     尽量减少小数据量频繁的数据插入。

·     当本地数据文件数据量特别大,考虑搭建共享存储访问,使用copy … on any node语句,这样所有节点都可以同步解析加载数据,提高数据加载的性能。

·     使用copy加载数据完成后,若入库数据量与实际数据量不一致,可通过查看各节点CopyErrorLogs目录,获取加载错误的数据信息,分析加载错误原因。

·     若加载流数据,或者对数据的实时性要求较高,推荐使用kafka进行数据加载。

·     在配置kafka调度器加载之前,通过手动copy加载少量kafka数据,以测试kafka集群和DataEngine MPP集群的联通性,是一种很好的方法。


6 SQL查询调优

DataEngine MPP数据库基于代价的优化器会权衡所有执行查询的策略并选择代价最小的策略去执行。

当用户向DataEngine MPP提交查询进行处理时,DataEngine MPP查询优化器会自动选择一组操作来计算请求的结果。所有这些操作称为查询计划。操作的选择会显著影响计算查询结果所需的资源量以及整体运行性能。最佳性能在很大程度上取决于可用于给定查询的projections。

当查询运行得比预期慢时,用户可以查看优化器选择的计划以及它为计划的每一步计算出的代价。这将帮助用户确定哪些步骤消耗了最多的资源,然后修改查询或者模式来为优化器提供更加有效的执行方法。用户可以使用SQL语句EXPLAIN 来查看查询的执行计划。

优化器基于为表生成的统计信息产生计划。精确的统计信息对于产生最好的执行计划非常重要。有关更新统计信息的方法请见更新统计信息小节。

6.1  如何生成执行计划

EXPLAIN和PROFILE语句是查询原因并改进查询性能的有用工具。 EXPLAIN会为查询显示其查询计划和估算的代价,但是不执行该查询。PROFILE 除了显示查询的查询计划之外,还会执行该查询。

PROFILE可以传递以下信息:

·     每个运算符分配多少内存和多少线程

·     查询执行期间,数据如何在不同时间流经每个运算符。

·     查询是否受网络限制。

建议在MC上执行查询计划和profile操作,因为在MC上操作,可以更直观的看到执行计划树以及执行过程中的资源使用,这样更便于分析。详情请查看MC监控小节中的查看profile和执行计划信息小节。

6.2  如何阅读执行计划

执行计划是一份报告,它详细描述了DataEngine MPP数据库优化器执行查询要遵循的步骤。执行计划的输出记录了优化器选择的执行计划信息,它的原文是以树形结构展现的,优化器的每一个操作显示为它的每一行,从执行计划可以看到以下内容:

·     语句中使用到的表

·     优化器评估的代价

·     优化器评估的行基数

·     PathID、错误信息代码、概要计数器使得能够很轻易的诊断性能问题

·     对数据的操作,SORT,FILTER,LIMIT,和GROUP BY

·     使用的projection

·     统计信息的状态信息

·     选择用于查询操作的算法,例如HASH/MERGE或GROUP BY HASH/GROUP BY PIPELINED

·     集群节点间的数据重新分发方式(广播,分段)

 

下面是一个查询计划:

 

其中:

·     Operators:运算,例如JOIN,SORT,FILTER,LIMIT。

·     网络运算符(operators运算可能引发节点之间网络流动)。

¡     RESEGMENT:数据量大时代价高

¡     BROADCAST:数据量大,节点多时代价高

·     Cost:成本,优化器对每步操作资源(CPU,memory,network)消耗的综合估计,受下列统计信息影响:

¡     表的行数

¡     列的基数

¡     列的最大,最小值

¡     列的值分布方式

¡     列占用空间

所以及时更新统计信息很重要。

·     Projection:优化器根据最低成本选择来相应查询

·     Column Materialization:物化(读取)的列

·     Path ID:优化器指定给每个操作的一个整数标识,可用于在profile跟踪查询执行情况。

6.3  优化查询方法

6.3.1  整体优化方法

很多SQL语句的性能问题可以通过调用函数 ANALYZE_STATISTICS()解决;如果更新统计信息之后查询仍然低效可以通过DB Designer的增量Designer解决;没有数据的Projection是不可能有全量统计信息,可以通过表 PROJECTION_STORAGE 检查是否有数据和 PROJECTIONS 的字段 HAS_STATISTICS 是否有统计信息;系统运行良好的情况下可以导出所有表的统计信息。

优化器会自动选择最优的 Projection 返回给查询语句,在有多个 Projection 可选的情况下, DataEngine MPP根据以下标准选择在执行计划中使用哪个 Projection:

·     查询语句中列是如何关联的

·     Projection 的分组和排序方式

·     是否有分析函数操作

·     Projection 在磁盘存储的列的信息

因此,对于projection的设计及优化就很重要了。可以通过提供少量样例数据,运行一下Database Designer的方式,来获取到合理的projection设计建议,这包括列的压缩,排序以及表的分布方式。

6.3.2  优化Join操作

DataEngine MPP提供hash join和merge join两种关联方式。

1. Hash join

当联接表的projection尚未在联接列上排序时,使用哈希联接。在这种情况下,优化器会在内部表(小表)的join列上构建内存中的哈希表。然后,优化器扫描外部表以查找与哈希表的匹配项,并相应地连接两个表中的数据。如果整个哈希表都可以放在内存中,则执行哈希联接的成本很低。如果哈希表必须写入磁盘,则成本会显著增加。

因此,如果关联的表没有在关联列上排序,且小表完全可以放入内存中,可以将小表作为内部表(位于操作符左侧的是外部表,位于操作符右侧的是内部表),查询性能会更好。

2. Merge join

Merge join在联接表上对联接列进行排序时使用。合并联接比hash join更快,占用的内存更少。

如果遇到期望使用 merge join却得到hash join的情况,这是由于一个Projection的关联列没有进行排序,为实施merge join,对要join的表创建一些针对join谓词进行排序的projection。谓词列应该位于order by的第一列。

对于大表的关联,应实行一致分段策略(segment列中包含join列),并对join列进行排序,使用merge join,以避免关联过程中可能出现的内存不足问题。

6.3.3  优化Group by操作

DataEngine MPP有两种聚合方法,分别是GROUPBY PIPELINED和GROUPBY HASH。

1. GROUPBY PIPELINED

在projection中,对group by的列进行排序时,使用该聚合方法。该方法只将聚合相关的数据放到内存中,因此,该聚合方式会节省大量内存且执行速率会比GROUPBY HASH要快。当需要聚合大量不同数据时,查询性能会有显著提升。

2. GROUPBY HASH

在projection中,未对group by处理的列进行排序时,使用该聚合方法。在执行聚合之前,数据库必须先建立一个hash表。

为避免group by过程中的重分段操作,应该在group by列表中包含segment列表(即group by列表范围要大于等于segment列表)。

6.3.4  其他

·     针对常用的,耗时较大的group by操作,可以考虑使用实时聚合projection来进行优化。

·     可以使用扁平表,以减少关联时的运算,提高性能和吞吐能力。

·     对于一些查询,用户可能希望影响优化器以在执行给定查询时做出更好的选择。在这种情况下,用户可以使用direct query来创建查询计划,该查询计划优先于优化器可能另外创建的任何计划。


7 高可用性

当用户启用并且正确地配置DataEngine MPP高可用特性时,DataEngine MPP数据库支持高度可用的、容错的数据库服务。要保证达到要求的服务等级,每个组件都必须有一个备用组件以保证在它失效时及时顶上。

7.1  磁盘存储

源于DataEngine MPP数据库的非共享MPP架构,每个数据库节点都有它们自己独立的内存和磁盘存储空间。为了兼顾可靠性和高性能,推荐采用8到24块磁盘的硬件RAID存储解决方案。当采用RAID5或RAID6时,大量的磁盘会提升I/O吞吐量,因为条带会增加并行的磁盘I/O。有一个失效磁盘时,RAID控制器能够继续工作,因为它在每个磁盘上都保存了校验数据,这样它能够重构阵列中任何失效磁盘上的数据。如果配置了热备盘(或者配置了能够用新磁盘替代故障磁盘的操作器),控制器能够自动重建故障磁盘。

在RAID1模式下,实际上就是镜像一组磁盘,因此如果出现某块磁盘故障,替代磁盘立即可用,并且性能与出现磁盘故障之前无二。

在RAID5模式下,故障磁盘上的每一个数据I/O都必须从剩余活动磁盘上重建出来,直到故障磁盘重建完成,因此会出现一段时间的性能下降。

如果磁盘数据重建期间,DataEngine MPP数据库提供了至少一个副本的镜像数据,镜像数据放置在其他节点上,以保证数据库的正常可用性。

RAID磁盘阵列仍然可能会出现单点故障,例如整个RAID卷故障。在硬件级别上,可以通过RAID控制器提供的镜像功能或操作系统提供的镜像功能来防范磁盘阵列故障。

定期监控每台主机的可用磁盘空间是很重要的。在执行占用大量磁盘空间的操作(例如copy大表)前要确保检查可用磁盘空间。

7.1.1  最佳实践

·     使用带有8到24个磁盘的硬件RAID存储方案。

·     使用RAID5,这样磁盘阵列能容忍一个失效磁盘。

·     在磁盘阵列中配置一个热备,以允许在检测到磁盘失效时自动开始重建。

·     通过镜像RAID卷防止整个磁盘阵列的失效和重建期间的退化。

·     定期监控磁盘利用并且在需要时增加额外的空间。

·     监控节点数据是否倾斜,以确保数据被均匀地分布在所有节点上。

7.2  数据库高可用性

DataEngine MPP通过维护数据的多个冗余备份来实现高可用性。DataEngine MPP保证冗余数据被散列存储在不同的的数据节点上,从而实现了冗余功能。DataEngine MPP将其称为K-safety,K表示数据库集群中数据被复制的次数。对于生产环境,DataEngine MPP建议将数据库的KSAFE值设定为1(生产环境有效的KSAFE值为1或2),即在数据库中,每份数据都至少有一个副本,被存放在不同的节点上。非生产库可设置为0。具有KSAFE的数据库必须至少有三个节点。K为1,数据库至少需要三个节点;K为2,数据库至少需要5个节点。

在DataEngine MPP中,K值可以设置为0、1、2。如果ksafety设置为1时,数据库任意一个节点宕机,不影响数据库正常运行。Kafety设置为2时可确保任意两个节点出现故障时DataEngine MPP可以正常运行。如果其他节点出现故障,只要数据库保存一份完整数据,数据库可以继续运行。

如果集群中故障节点数超过集群一半及以上时,数据库会被认为是不安全的,并会自动关闭。

 

7.3  双集群

在特定场景下,可以通过维护两个存储同样数据的DataEngine MPP数据库集群提供额外层次的冗余。实现双集群的决定应该考虑到业务需求。

在双集群配置中为了保持数据同步,有两种推荐方法。

·     第一种方法被称作双ETL。

¡     ETL(抽取、转换和装载)是常见的清理、转换、验证并且将数据装载到数据仓库中的数据处理工具。通过双ETL,ETL处理会被以并行的方式执行两次,每个集群上一次,并且每一次都会做验证。

¡     双ETL提供了一个存有相同数据的备用集群。它还提供了在两个集群上查询数据的能力,并使得处理吞吐量翻倍。应用可以根据需要利用两个集群,还要确保ETL在两边都成功并且被验证。

·     维护双集群的第二种机制是集群拷贝。

¡     通过vbr的copycluster方式,将数据从主集群直接复制到备用集群上。Copycluster也支持增量拷贝,对于按每天或者更低频率进行数据同步。此方式是集群备份的理想方案。

7.3.1  最佳实践

为了提供额外级别的冗余安全和额外的查询处理吞吐量,可以考虑双集群配置。

7.4  备份和恢复

除非数据库中的数据可以很容易并且很干净地从源数据再生,否则推荐为DataEngine MPP数据库进行备份。备份可以防止操作错误、软件错误或者硬件错误。

DataEngine MPP可以对数据库中的某些对象或者整个数据库进行备份与恢复操作,同时还支持对整个数据库迁移到另一个同等规模的集群。

DataEngine MPP的备份可以在本机实施,也可以通过配置备份主机在集群外其它机器进行。DataEngine MPP的备份可以分为全备份(FULL BACKUP)和增量备份(INCREMENTAL BACKUP)。

7.4.1  最佳实践

·     建议在数据库内容发生大的改变时进行备份。如加载大量数据,节点发生故障,数据库增加、删除或替换节点。

·     备份位置可以为集群内主机或集群外主机,若将数据备份到集群外主机,需确保集群和备份主机间的Python和rsync版本一致,并配置主机间数据库管理员用户的的SSH免密。

·     确保备份主机有足够的磁盘空间。

·     每次使用相同的配置文件备份数据库时,都会创建一个增量的备份,并且可能会删除最旧的备份。

·     备份恢复配置文件中的restorePointLimit参数控制存储备份的数量,该参数默认值为1,即只保存两份备份文件,在进行增量备份时,会循环删除最早的备份文件。可修改该参数值以保存更多的备份文件。

·     还原数据库时,可选择从任何保留的备份进行恢复,若希望访问较早的备份,可修改restorePointLimit参数限制。

·     在将源集群数据备份到另一个数据库集群时,需确保目标集群与源集群有相同数量的节点、同名的数据库、相同的节点名称、相同的数据库管理员账户且所有节点均配置了源数据库管理员SSH免密登录。

不同款型规格的资料略有差异, 详细信息请向具体销售和400咨询。H3C保留在没有任何通知或提示的情况下对资料内容进行修改的权利!

新华三官网
联系我们