商城网站开发视频邯郸网站设计邯郸网站制作
news/
2025/10/5 19:28:46/
文章来源:
商城网站开发视频,邯郸网站设计邯郸网站制作,天津黑曼巴网站建设,佛山网站建设公司如何组建简介#xff1a; 《实时数仓入门训练营》由阿里云研究员王峰、阿里云资深技术专家金晓军、阿里云高级产品专家刘一鸣等实时计算 Flink 版和 Hologres 的多名技术/产品一线专家齐上阵#xff0c;合力搭建此次训练营的课程体系#xff0c;精心打磨课程内容#xff0c;直击当下…简介 《实时数仓入门训练营》由阿里云研究员王峰、阿里云资深技术专家金晓军、阿里云高级产品专家刘一鸣等实时计算 Flink 版和 Hologres 的多名技术/产品一线专家齐上阵合力搭建此次训练营的课程体系精心打磨课程内容直击当下同学们所遇到的痛点问题。由浅入深全方位解析实时数仓的架构、场景、以及实操应用7 门精品课程帮助你 5 天时间从小白成长为大牛视频链接:https://developer.aliyun.com/learning/course/807/detail/13889 内容简要 一、Hologres建表最佳实践 二、Hologres性能问题分析与优化 一、Hologres建表最佳实践 一建表优化的必要性 为什么Hologres建表优化非常重要 首先对于整个的查询性能以及写入性能来讲一个好的建表跟一个比较差的建表性能上面有非常大的区别。 其次建表优化需要尽早做是因为Hologres在改 DDL的同时有可能需要用户重复进行一些数据导入这种重复的工作使得我们希望尽早完成建表优化。 最后一个好的建表对于用户的数据存储成本也有一定的帮助。如果建表做得不恰当可能导致建一些不必要的Index然后导致数据多了一些冗余的存储从而提升了成本。 因此建表优化是非常重要的这也是把它作为本文第一部分的原因。 二业务建模是性能优化的前提 说完建表的重要性之后我们再看建表优化之前要去做整个业务建模的优化。在考虑使用Hologres的同时我们要知道通过Hologres能够解决什么样的业务问题以及通过什么样的方式解决。 Hologres本身是一个HASP产品在使用Hologres的同时就需要跟业务场景结合我们要知道这个场景到底是分析场景还是在线服务场景。如果是一个分析型就用Hologres的列存比较友好如果是一个在线服务型场景就用行存比较友好这些是跟业务场景相关的。 第二个是要能够结合Hologres本身的产品优势。Hologres是一个在线服务以及交互式分析的产品它并不适合ETL以及海量数据拖取的场景。因此在把业务往Hologres上面搬的时候不能搬所有的场景否则可能导致Hologres做一些不太适合本身的事情信任就会不太好。 第三个是需要做一些取舍。为了达到预期的性能可能需要做一些类似预计算或者数据加工的提前操作减少后续计算复杂度加快计算速度。 以上这些都跟预先数据建模以及整个业务期望息息相关。 三存储方式的选择 做完以上准备工作之后我们需要进行Hologres管理存储方式的选择。 Hologres本身支持两种存储方式分别是行存和列存。 行存主要的应用场景是对主键进行高QPS查询并且当我们表比较宽的时候一次查询会读取大量列这种场景适用Hologres是非常适合的。 除此之外 Blink的维表查询必须是用行存因为一般情况下Blink的维表是高QPS、基于Key的查询列存没有办法扛住这么高的压力。 列存适用于复杂的交互式分析查询比如一个查询里面它有关联、聚合等等各种各样的复杂计算。同时它覆盖的场景非常多包括过滤、聚合等列存是比较通用的存储方式。 行存主要适用于在线服务类的场景列存主要适用于分析型的场景这是两个存储方式的选择区别。 四优化Shard数 Shard_count: Shard实现了物理分表的效果多个Shard并行服务查询。 增加Shard可以增加查询的分布式并行度更多Shard不一定查询更快也会带来并发查询的调度开销。 说完存储方式接下来我们看Shard数。 Hologres在存储的时候是把物理表分成一个个Shard存储每个表会按照一定的分布方式分布到所有的物理节点上面然后每个Shard可以去并发进行查询Shard数越多相当于整个查询的并发度越高。但是Shard数也不是越多越好因为它本身有一些额外的开销所以我们需要根据整个查表的数据量以及查询复杂度来设计每个表的Shard数。 在集群扩容的时候比如我们原本是128 Core的实例扩容到256 Core之后我们需要对整个Shard数进行一定的调整这样才能享受扩容带来的性能提升。 因为我们整个并发度是在Shard数上面假如实例扩容了但是Shard数没变那么相当于整个计算的并发度没变这种情况会导致虽然扩容了但是查询性能没有提升。 一般情况下我们会建议用户将Shard数设置成跟实例规格差不多的数量比如一个64 Core的Shard数设成40或64这种比较贴近于实例规格的数量。当规格往上涨之后我们希望Shard数也能往上涨从而提高整个查询的并发度。 五优化Distribution Key 然后说完Shard数之后我们再看一下Hologres里面非常重要的Distribution Key它主要是用来决定数据如何分到每个Shard上面。 Distribution_key:均衡地分发数据到多个Shard中令查询负载更均衡查询时直接定位到对应Shard。 如果创建了Primary Key索引用于数据更新默认为distribution_key Distribution_key如果为空默认是RandomDistribution_key需是Primary Key的子集。 一个好的Distribution Key设计首先要求用户的数据在Distribution Key上划分比较均匀。 比如用户ID或者是商品宝贝ID一般情况下Key只有一个所以它是非常均匀的是用来作为Distribution Key非常好的例子。但是像年龄或者性别这种就不太适合作为Distribution Key因为它可能会使大量的数据Shuffle到一个节点上导致整个数据的分布不是很均匀。 Distribution Key主要的作用是减少关联查询、聚合运算里数据的Shuffle。 如果用户没有设置Distribution Key那么我们默认是Random因为我们会保证用户的数据能够尽可能均匀地分布到所有Shard上面。 接下来我们看一下Distribution Key主要的作用。 在Hologres里面我们会有不同的表放到不同的TableGroup里面对于Shard数相同的表都会放到一个TG下面。 假设两个表做关联如果都按照关联的Key去设计Distribution Key那么这两个表的关联就可以做一个Local Join如上图左边所示。所有的数据不需要做额外的Shuffle每个表在每个Shard上面做完关联之后直接产生结果。 假如数据量增大之后可能需要扩容我们希望在这个TG下面所有表都会进行扩容这样能保证数据分布的一致性维持住整个Local Join而不会因为扩容导致做不了Local Join。 Local Join相比于非Local Join性能差别非常大通常会有一个数量级左右的差异。 跟Local Join最相关的就是Distribution Key的设计如果Distribution key设计不合理时在Join时可能引起大量的Data Shuffle影响效率。 如上图所示假设表A跟表B要做一个关联如果不是Distribution Key的场景那么我们就需要把表A的数据跟B的数据都按照它的Join Key做Shuffle Shuffle会带来非常高昂的成本同时影响整个查询的效率。 所以通常情况下对于需要连接的表可以把Join关系设为distribution key实现Table在同一个Shard内Local Join。 六优化分区表 分区表:也是物理表具备一样的Shard能力但多了一个根据分区键进行Table Pruning的能力。 如上图所示假设查询的过滤条件只命中了部分的分区那么剩下的分区表就不需要进行扫描这能够大大节约整个查询的IO加快查询速度。 通常情况下分区的Key是静态的并且数量不会太多最适合做分区Key的是日期。例如有的业务方是一天一个分区或者按小时分区那么查询的时候也会按照某一段时间来过滤数据。 通过分区表当用户的查询条件包含时间过滤时就可以把不必要的分区过滤掉对查询性能有很大的的提升。 通常将日期列等基数低小于一万)的字段用于做分区字段如果分区表过多 而查询时不带有分区过滤条件性能会下降。 七优化Segment Key Shard是一个逻辑数据单位物理上是一组文件分发到同一个Shard的多个表以及对应的索引。 Segment Key主要是作用于列存。 在列存上面文件是存成一个个Segment当查询到了某一个Shard上因为Shard内部有一堆的文件我们要去找哪些文件会命中这个查询需要进行扫描Segment Key是用来跳过不需要查找的文件。 假设Segment设成了一个时间数据按照时间写入比如10点到11点是一个文件11点到12点是一个文件12点到13点是一个文件。当我们要查询12:15~12:35区间范围的数据对于这种情况通过Segment Key就能快速找到12点到13点这个文件命中查询所以只要打开这一个文件就可以了。通过这种方式就可以快速跳过不必要的文件扫描减少IO让整个查询更快。 上图主要是介绍了整个数据的写入流程帮助大家理解Segment Key到底是什么样的。 刚才提到当数据写入Hologres会写到内存表里面内存写满了异步Flush到文件Append Only写入写入效率最高。因为写入时为了性能没有全局排序和单文件更新文件之间存在Overlap。 这是什么意思 Segment_key用于文件块的边界划分查询时基于Segment_key可以快速定位数据所在文件块 Segment_key多列时按照左对齐。 如上文提到的例子11点到12点在一个文件是比较理想的情况实际情况可能是11点到12点在一个文件11:30~12:30是在第二个文件里面12:30 ~13:00又是一个文件文件之间可能存在重叠。查询可能会命中多个文件这种场景可能就会导致需要打开多个文件。 所以在设计Segment Key的时候尽可能不要有Overlap尽可能顺序地递增。如果数据写入非常无序比如写进来的数据先是123然后678然后456这种乱序的写入就会导致Segment Key可能在不同的文件内部有重复的数据使得Segment Key完全没有起到查询过滤的作用。 因此设计Segment Key最关键的一点就是尽可能单调并且没有Overlap这样才可以让我们能够尽可能跳过这种不必要的数据扫描。 Segment Key的设计主要是用在Blink的实时写入场景并且把Key设成时间字段因为它数据实时写入的时间是递增的并且每个值不会有很大的 Overlap比较适合用Segment Key。 除此之外其他的场景不太建议用户自己设Segment Key。 八优化ClusteringKey Clustering_key文件内聚簇布局表示排序信息和MySQL 的聚簇索引不同Hologres用来布局数据不是布局索引因此修改Clustering需要重新数据导入且只有一个 Clustering_key排序操作在内存中完成生成SST。 上图为一个例子上图的左边是一个完全无序的情况如果按照Date作为ClusteringKey那么会变成右上角的图。按照Date做完排序之后当进行Date查询比如Date大于1/1小于1/3的数据可以快速查到对应的时间段。 假设没有做这个Index我们就需要把所有数据都扫一遍这就是通过ClusteringKey加速查询的原理。 假设按照Class做排序如果将Class和Date作为ClusteringKey那么会先按照Class做排序然后再按照Date排序如上图右下方所示。对于这种场景ClusteringKey的设计是按照最左匹配的原则就是当遇到用户的查询条件也按照最左匹配的原则来匹配。 例如查询的Key是Class那么能够命中ClusteringKey如果查询条件是Class跟Date也能够命中ClusteringKey但如果查询条件只有Date则无法命中ClusteringKey。遵循的最左匹配相当于从左往右的条件中无论用户的查询条件有几个最左边的条件必须匹配上才可以。 ClusteringKey主要的作用是能够加速查询的过滤Range查询的过滤以及点查的过滤。 ClusteringKey的缺点是每个表最多只能有一个ClusteringKey只能有一种排序方式。 九优化字典编码 字典编码对于字符串类型可以有效压缩特别是基数小的列。编码值可以加快比较操作对于Group ByFilter有好处Holo在0.9之后自动设置。 上图为字典编码的一个例子。 如上图左边所示有Card No和男女性别Gender。因为男女性别只有两个值所以非常适合于用字典编码假如把性别编码成0跟1就变成了图中间的方式。 当进行数据查询的时候需要对过滤条件的编码比如想查所有男性的Card No过滤条件就变成了Gender 0通过这种方式进行数字查询。 但是字典编码有一个缺点就是对于基数列比较大的场景它的开销非常高。 因为我们对数据先进行编码编码的过程中假如数据一共是100万行其中有99万行不一样的值这会导致我们有99万个Encoded值这种情况会造成整个编码跟查询的耗损非常高这种情况就不太适合做字典编码。 在Hologres0.9之后我们支持自动设置字典编码用户无需自己去配置字典编码。 十优化位图索引 位图索引对于等值过滤场景有明显的优化效果多个等值过滤条件通过向量比较计算。 位图索引相当于把每列的数据通过位图来标识它是否存在。 如上图所示我们将左边表中学生的性别、班级进行位图编码就得到了右边的图通过这些位图信息我们可以进行快速过滤。 例如我们要查所有男性学生可以通过“1 0”进行过滤得到右图中PK值为1、2、5、6这四行符合查询条件的数据。假设要过滤出三班的同学那么我们再构建一个位图“0 0 1”再跟班级的数据做一个过滤就能得到PK值为2和6的信息。 可以看到位图索引主要的应用场景是在点查比如查询条件是男性并且年龄等于32岁这种场景也是非常适合用位图进行查询加速。 同样的位图索引也有个问题就是基数过多的列在位图索引编码时会形成稀疏数组列很多值很少对查询性能改善影响小。 十一物理拓扑 上文阐述了几个索引以及整个存储方式下面看一下如何区别它们以及整个用户视角看起来它大概是什么样的抽象。 如上所示用户写了一个SQL之后首先会按照用户分区键路由到对应要找的表上面找对逻辑对象Table。 第二步通过Distribution Key找到对应Shard。 第三步是Segment Key找到Shard之后要找对应Shard上面的文件因为实际数据是存储成一个个文件我们通过Segment Key找到想要打开的文件。 第四步是在文件内部数据是否有序这是通过Clustering Key来查找的Clustering Key帮助我们找对实际文件区间。 第五步是Bitmap。因为Hologres把数据按照一个个Batch存储在一个Batch里面我们需要通过Bitmap快速定位到某一行否则需要把某一个区间范围内所有的数据扫一遍。 图中从上往下不同的过程越来越到文件内部越往上是越大的范围。 二、Hologres性能问题分析与优化 一性能白皮书 用户问得最多的问题是Hologres的性能如何我们有一个大概的性能估量。 使用Hologres时实时写入单Core的QPS是5000对于离线写入的场景比如Max Computer写入到Hologres通常情况下单Core的QPS能到5W。对于OLAP查询单Core处理200万数据量。对于点查场景单Core QPS在1W左右。 用户可以根据以上信息来评估自己的查询以及业务场景需要用多少资源。 二实时写入与点查 对于不同的应用场景我们优化手段是不太一样。 对于实时写入与点查的场景首先要检查建表是否合适。对于高QPS写入以及点查来说我们希望Distribution Key和查询条件一致。因为Distribution Key用来找到对应的Shard在写入的QPS很高的情况下假如过滤条件与分布Key一致我们就可以快速路由到某一个Shard上面这个查询就不需要发到所有Shard上对这种场景有很大的性能提升所以要求Distribution Key和查询条件一致。 第二个是我们的表最好是行存表因为行存表对实时写入以及点查在性能上非常友好。 第三个场景是假设不是行存表而是列存表我们希望Pk、Clustering Key和查询条件一致这样才能用上Clustering Index的能力。 除了建表优化以外还需要优化查询写入代码。因为如果写Hologres的代码设计得不合理会带来非常高昂的额外成本。可能用户会发现QPS好像已经上不去了但其实Hologres内部CPU使用率非常低这是因为用户自己的写入代码不是特别高效。 对于这样的问题首先我们希望用户尽可能通过Preparestmt的方式它主要的好处是能够节约整个执行计划的开销。提交一个SQL之后一般会把 SQL进行编译解析然后生成一个执行计划最后提交到执行引擎来执行这样的一个过程。当数据重复执行SQL的时候使用Preparestmt就可以不用再去做生成、执行计划、解析的过程成本大大减少查询和写入的QPS会更高。 第二点是我们希望用户写入的数据尽可能凑批。比如说我们经常会碰到一些用户他会先写insert into values1和insert into values2再写insert into values2和insert into values3然后不停地发这种小的SQL进行数据插入这会带来非常高昂的数据RPC成本同时整个QPS也上不去。 我们通过凑批可以让写入性能会高很多比如通过insert into values的方式一个values里面就包含了1000个值或者1万个值这1万个值的写入只要一次数据传输就可以了。相比于之前的方式性能上可能存在1万倍的差异。 第三块是整个Holo Client的使用有的用户可能不太清楚如何优化代码或者不能凑好批Holo Client可以帮助用户解决这些问题。 相比于传统的JDBC ClientHolo Client帮用户做了各种各样异步化的封装以及凑批的逻辑并且它没有SQL引擎的额外开销不需要进行一些SQL解析的操作所以它的写入跟查询性能相比于使用JDBC的方式会好非常多。 Holo Client也是Blink Client写入的内置插件所以它相比用户自己的工具写入性能会更好。 还有一点是我们连接的时候尽可能使用VPC域名进行数据的写入跟查询。 因为直接用公网的话网络之间的RT比较高。如果用VPC网络因为是在同一个网站内机器之间的RT比较低能够减少整个网络上面的开销在很多应用场景下它的影响非常大也非常重要。 二离线写入与查询常见问题 接下来我们看一下离线写入与查询常见的问题。 为什么把离线写入跟查询放在一起这是因为离线写入跟查询是一样的原理离线写入也是通过跑一个Query跑Query方式的问题都是差不多的。 首先是统计信息缺失。 Hologres本身是一个分布式引擎它要把用户写的SQL运行在分布式引擎上因此需要去优化器生成一个执行计划优化器需要统计信息来帮助它生成一个比较好的执行计划。当遇到用户统计信息缺失优化器相当于丧失了输入无法生成执行计划这是我们在线上遇到最大也是最多的一个问题。 第二个很大的问题是建表不优当遇到建表跟查询不一致的情况就会导致整个查询的性能非常差。 除此之外Hologres是一个自研的引擎但是为了兼容Postgres的开源生态所以会有一个联邦查询的机制使得用户能在Postgres运行的Query也能在Hologres运行但是它会带来一些额外的性能损失。 三查看执行计划 执行计划的好坏对于查询性能影响非常大。Hologres的查询优化器会根据 Cost选择执行耗时最低的查询计划来执行用户的查询不过难免会出现一些查询计划不优的情况。用户可以通过Explain命令来查询执行计划执行计划中一般包含以下算子 1.数据扫描算子Seq Scan、Table Scan及Index Scan等。 主要是用来进行数据访问Seq Scan、Table Scan及Index Scan分别对应顺序扫描表扫描以及基于Index的扫描。 2.连接算子Hash Join及Nested Loop。 Hash Join的意思是两个表做关联的时候会先把一个表做成Hash Table另外一个表通过Hash Table的Lookup进行关联查询。 Nested Loop会把两个表做成两个For循环在外表就是一个表 For循环遍历所有的数据另外一个表也是For循环这就是Hash Join与Nested Loop的区别。 3.聚合算子Hash Aggregate及Streaming Aggregate。 基于Hash查找的AGG实现及基于排序的AGG实现。 4.数据移动算子Redistribute Motion、Broadcast Motion及Gather Motion等。 Hologres是一个分布式的引擎所以难免会碰到数据Shuffle的情况。Redistribute Motion主要是做数据的ShuffleBroadcast Motion是做数据广播Gather Motion是把数据拉到一起这些数据移动算子主要是用来解决分布式数据的问题。 5.其他算子Hash、Sort、Limit及Append等。 四统计信息缺失 我们在看Query性能的时候经常会碰到几个问题其中一个是统计信息缺失我们如何知道统计信息是否缺失 上方是一个explain查询的例子。当Hologres没有统计信息行数的默认值是1000。这里我们可以看到当前tmp和tmp1两个表的行数都是1000表明这两个表目前都拿不到统计信息。 没有统计信息容易出现的问题 跑查询OOM写入性能差五更新统计信息 那么我们怎么解决没有统计信息的问题 通过Analyze命令用户可以更新统计信息。 还是之前的例子通过analyze tmp;和analyze tmp1可以看到这两个表就有统计信息了如上方所示。 从上方可以看到tmp1有1000万行数据它1000万数据Join 1000行数据此时我们发现这个表虽然做了个Hash Join但它的Join顺序是不对的。因为在这之前tmp的数据量非常小而temp1数据量非常大会导致把tmp1放到了Hash Table这一侧然后Hash Table非常大导致整个Join性能非常差。 通过Analyze之后可以把Join的顺序调过来把小的表tmp放在被Hash这一侧把大的表tmp1放在关联的那一侧形成一个比较好的查询计划查询性能相比之前也有一个比较大的提升。 六选择合适的分布列 我们需要选择合适的分布列也就是本文前面提到的做Local Join的情况。如果用户不设置分布列在进行关联查询时Hologres需要将2个表的数据根据join key shuffle到一起保证数据的正确性。如果shuffle的数据量很大会造成很高的查询延迟。 我们如何判断有没有做Local Join 在上方示例中我们可以看到通过explain查看执行计划Redistribute Motion表示Shuffle算子tmp和tmp1两个表在做关联之前都通过Join条件作了Shuffle这说明整个关联不是一个Local Join。 解决方法是把关联Key设置成Distribution Key。 具体做法是重新建表关联Key设成a跟b此时我们再去查看执行计划就没有Redistribute Motion了这个关联就是一个Local Join。 通过这种方式就可以让整个关联从非Local Join变成了Local Join性能相对之前也有一个比较大的改善。 七判断是否用上Clustering Key 接下来看一下怎么通过执行计划来看我们之前的那些建表的Index判断是否用上Clustering Key。 如上方所示假如我们写了个查询explain select * from tmp where a 1; 假设a字段是个Clustering Key此时我们在explain查询的执行计划中可以看见有一个Cluster Filter表示我们已经用上Clustering Key。 八判断是否用上Bitmap 接下来我们判断是否用上Bitmap。 如上图所示我们的查询条件是explain select * from tmp where c 1; 这个c是Bitmap Key在执行计划可以看到有Bitmap Filter:c 1这样一个过滤条件此时我们就知道用上Bitmap了。 九判断是否用上Segment Key 接下来判断是否用上Segment Key。 如上图所示我们的查询条件是 explain select * from tmp where b 1; 这个b是Segment Key我们在执行计划可以看到有Segment Filter:b 1这样一个过滤条件此时我们就知道用上Segment Key了。 通过以上几个explain查询的例子我们就能知道查询是否用上之前建表的Index如果没用上说明有可能建表不对或者查询模式并没有很好地适配建表。 十联邦查询优化 在Hologres内部有两套计算引擎其中一套是完全自研的Holo计算引擎它的性能卓越但也是因为它是完全自研的所以相较于开源的Postgres计算引擎它无法在一开始就支持所有Postgres的功能会有部分Postgres功能缺失。 另一套计算引擎是Postgres它是完全开源生态的性能方面比自研的计算引擎稍差一些但是它完全兼容Postgres功能。 因此在Hologres里面一个查询有可能会既用到Holo计算引擎也用到Postgres计算引擎。 十一优化联邦查询 判断是否使用了联邦查询我们可以通过explain。 Hologres自研引擎不支持not in对于查询: explain select * from tmp where a not in (select a from tmp1) 如下所示 从执行计划可以看到有External SQLPostgres这样的一个算子这就标识了查询引擎跑到了Postgres引擎上面去执行。 因为Holo计算引擎不支持not in所以说这部分的计算是在Postgres上面执行的。当看见External SQLPostgres这个算子用户需要警惕当下用到了Holo计算引擎不支持的功能此时最好通过查询改写换成Holo支持的算子来执行它的Query从而提升查询性能。 对于上面这个例子的场景我们可以通过将not in 改为 not exist: explain select * from tmp where not exists (select a from tmp1 where a tmp.a); 当用户这个表一定是非空那么可以把not in直接改成not exit之后再查看执行情况会发现整个Query都是在Holo引擎上面没看到刚才的External SQLPostgres算子。 这个查询生成的执行计划相比之前在Postgres引擎上执行的计划查询性能上可能会有数倍的差别。 通过上述所有的例子我们就了解了Hologres性能调优整个过程以及其中需要注意的关键点欢迎感兴趣的同学多多关注与使用Hologres。 原文链接 本文为阿里云原创内容未经允许不得转载。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/928637.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!