doris实践分享-基于查询日志对doris查询优化

发布于:2022-12-14 ⋅ 阅读:(1244) ⋅ 点赞:(1)

1.背景

Doris的查询性能好坏,很大程度上取决于表模型的设计是否合理。数据开发同学在创建或优化表模型时,无法感知到用户真实的查询场景,只能根据自身对业务的理解来进行设计,开发成本较高;用户在使用Doris进行查询时,同样不清楚查询本身是否合理,也不容易感知到查询的表模型是如何进行设计的,难以提升用户的使用体验。当前我们公司解决方案是基于doris的查询审计日志,搭建doris性能优化看板,方便用户自行定位负载问题以及识别不合理的查询,提高Doris的整体查询效率。

2.Doris相关原理介绍

为了使看板的使用说明更容易被理解,下面首先将对Doris的一些基本原理进行介绍。

2.1    查询时长的决定因素

Doris定位为一款OLAP引擎,用户在使用时最关注的点必然是SQL的查询时长。从提交一个SQL到返回查询结果,这两个环节之间的时间长短,能直接决定用户查询体验好坏。

Doris的查询负载主要包括两大方面:1个是数据扫描(目前也是Doris最大的性能瓶颈),一个是计算(目前经验主要体现在bitmap计算上)。扫描的数据量越小、计算量越小,查询时间也会越快。

对Doris查询的扫描和计算的主要影响因素如下

表现 影响
数据扫描 表数据量大小 表模型类型 聚合模型/唯一主键模型 预聚合程度高 扫描数量小
冗余模型 无预聚合 扫描数据量大
ROLLUP 命中 扫描rollup表 扫描数量小
未命中 扫描base表 扫描数据量大
谓词过滤效果 分区分桶 过滤 扫描少量分区/分桶 扫描数量小
未过滤 扫描大量分区/分桶 扫描数据量大
前缀索引 过滤性能高 过滤大量数据 扫描数量小
过滤性能低 过滤少量数据 扫描数据量大
数据计算 逻辑复杂度 复杂度高 启动fragment个数多 计算量大
复杂度低 启动fragment个数多 计算量小
计算数据量 数据量大 启动instance个数多 计算量大
数据量小 启动instance个数少 计算量小

由于在计算上,因为计算逻辑与计算数据量都是和业务强相关,很难对计算本身进行大的优化(对去重指标可使用HLL),所以对于查询时长的优化更多地会体现在对扫描的优化上。

2.2    数据扫描优化方向

对Doris表模型的数据扫描优化,本质上就是让查询能够尽可能地少地扫描数据,达到通过减少扫描数据量来提升查询性能的效果。

根据上表可知,数据扫描优化主要分为2个大方向:减少表数据量大小、增加谓词过滤效果,其分别又能细分为:使用聚合模型、创建ROLLUP、使用分区分桶过滤、合理设置前缀索引。下面将分别对这4个方向的优化原理进行介绍。

1)聚合模型

当我们将数据导入聚合模型时,对于 Key 列相同的行会聚合成一行,而 Value 列会按照设置的 AggregationType 进行聚合。

通过预聚合后,Doris里实际存储的数据量,会小于导入前的数据量,以导入效率来换取查询时间。

2)ROLLUP

对于聚合模型来说,Rollup是从细粒度模型向更粗粒度的上卷,其本质上也是一个聚合模型。Rollup通过预聚合来减少数据聚合数据量,重新调整索引,以空间和导⼊效率换查询效率。不过其依托于base表,无法独立存在,用户也无法手动选择Rollup来进行查询。

用户可以选择在任意时刻选择创建Rollup,不需要额外对其进行数据的导入,当新建一个Rollup后,Doris会自动将表中的数据同步至新建的Rollup中(当表中数据量较大时,同步数据需要一段时间,此时表出于“Alter”状态,无法再添加新的Rollup)。

查询时用户对Rollup的选择是无感知的,Doris将前缀索引列依次匹配谓词列并计数,在若干个前缀最优匹配的rollup中,选取行数最少的rollup(即聚合度最高)作为最终结果。

注意:

key列相同且顺序相同的rollup的查询性能无差异,导入性能会由value列变多而轻微线性增长(仅增加聚合计算成本)。

如果不是在高基数维度下的bitmap列(bitmap计算成本最高,导入时rollup计算大量bitmap_union),建议rollup包含全部value列。

3)分区分桶

在 Doris 的存储引擎中,用户数据被水平划分为若干个数据分桶(Tablet)。每个 Tablet 包含若干数据行。各个 Tablet 之间的数据没有交集,并且在物理上是独立存储的。

多个 Tablet 在逻辑上归属于不同的分区(Partition)。一个 Tablet 只属于一个 Partition。而一个 Partition 包含若干个 Tablet。因为 Tablet 在物理上是独立存储的,所以可以视为 Partition 在物理上也是独立。Tablet 是数据移动、复制等操作的最小物理存储单元。

若干个 Partition 组成一个 Table。Partition 可以视为是逻辑上最小的管理单元。数据的导入与删除,都可以或仅能针对一个 Partition 进行。

查询时添加分区/分桶的过滤条件,Doris在执行时会只扫描对应的分区/分桶的数据,能高效地降低实际扫描的数据量,提高查询性能。

4)前缀索引

Doris 会把 Base/Rollup 表中的前 36 个字节(有 varchar 类型则可能导致前缀索引不满 36 个字节,varchar 会截断前缀索引,并且最多使用 varchar 的 20 个字节)在底层存储引擎单独生成一份排序的稀疏索引数据(数据也是排序的,用索引定位,然后在数据中做二分查找),然后在查询的时候会根据查询中的条件来匹配每个 Base/Rollup 的前缀索引,并且选择出匹配前缀索引最长的一个 Base/Rollup。

能匹配前缀索引的谓词条件需要是"=、<、>、<=、>=、in、between",并且这些条件是并列的且关系,使用and进行连接,对于”or、!=“等这些不能命中。

3.Doris审计日志

为了能够使创建的Rollup及前缀索引更加客观、准确地反应用户真实的查询需求,这里需要使用Doris官网提供的审计插件        https://doris.apache.org/zh-CN/docs/ecosystem/audit-plugin  

收集数据的表结构如下:

create table doris_audit_tbl__
(
    query_id varchar(48) comment "Unique query id",
    time datetime not null comment "Query start time",
    client_ip varchar(32) comment "Client IP",
    user varchar(64) comment "User name",
    db varchar(96) comment "Database of this query",
    state varchar(8) comment "Query result state. EOF, ERR, OK",
    query_time bigint comment "Query execution time in millisecond",
    scan_bytes bigint comment "Total scan bytes of this query",
    scan_rows bigint comment "Total scan rows of this query",
    return_rows bigint comment "Returned rows of this query",
    stmt_id int comment "An incremental id of statement",
    is_query tinyint comment "Is this statemt a query. 1 or 0",
    frontend_ip varchar(32) comment "Frontend ip of executing this statement",
    cpu_time_ms bigint comment "Total scan cpu time in millisecond of this query",
    sql_hash varchar(48) comment "Hash value for this query",
    sql_digest varchar(48) comment "Sql digest for this query",
    peak_memory_bytes bigint comment "Peak memory bytes used on all backends of this query",
    stmt string comment "The original statement, trimed if longer than 2G "
) engine=OLAP
duplicate key(query_id, time, client_ip)
partition by range(time) ()
distributed by hash(query_id) buckets 1
properties(
    "dynamic_partition.time_unit" = "DAY",
    "dynamic_partition.start" = "-30",
    "dynamic_partition.end" = "3",
    "dynamic_partition.prefix" = "p",
    "dynamic_partition.buckets" = "1",
    "dynamic_partition.enable" = "true",
    "replication_num" = "3"
);

    

4.doris优化看板产品设计思路 

基于审计日志数据,可以开发一个doris优化看板产品,主要包含以下内容:

4.1模型优化

基于审计日志数据,排除查询逻辑不健康的情况,数据模型的优化大多会落在创建更合理的Rollup、创建更合理的前缀索引这两个点上。

通过对历史查询日志的汇总,对高频查询维度的顺序、组合进行计算,推荐相对合理的Rollup供开发者参考。

同时对于经验较为丰富的开发者,也可自行结合字段热度进行分析,并创建相应Rollup。

4.2查询追踪

对于Doris的查询用户,可通过对查询SQL打标的方式,快速获取自己查询日志的明细指标,判断性能瓶颈。

用户可对不合理的查询进行优化,对于高频合理查询也能联系开发同学进行模型优化。

为方便大家快速学习doris知识,我这边也整理了一份doris脑图,点击doris实践分享-基于查询日志对doris查询优化,回复doris脑图自动获取。

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到