写点什么

基于 Impala 的网易有数 BI 查询优化总结

2021 年 2 月 22 日

基于Impala的网易有数BI查询优化总结

网易云音乐数仓2020年建设之路》一文提到了 Impala 性能优化工作对于音乐数仓建设的重要性,本文总结了 Impala 在网易数帆旗下有数 BI 应用场景下的最新查询优化经验,并探讨后续进一步优化的思路。文章首先简述有数 BI + Impala 在网易云音乐等业务使用时遇到的挑战,再介绍进行有数查询优化的重要工具——网易 Impala 管理服务器,最后结合实际业务问题讨论具体优化方法及下一步计划。

一、有数 BI + Impala 遇上慢查询

在网易数帆旗下的全链路数据生产力平台中,有数商业智能(BI)产品提供了数据大屏、有数报告(EasyBI)和自助取数(EasyFetch)等服务。


自助取数面向的用户是数据分析师,有数报告所面向的用户是 BI 工程师,允许用户直接通过拖拽 UI 界面的各种控件来获取所需的取数结果或数据报告,能够减少数据开发等相关工程师的工作量,大大提高分析师取数的效率和 BI 报告制作效率。



目前,有数产品在包括网易云音乐、严选、传媒等在内的网易集团内部业务,以及包括德邦快递、名创优品、温氏集团、古茗等外部客户的业务上均大规模使用。


世上武功,唯快不破。对于自助取数和有数报表,用户体验非常重要的一点就是要快。目前有数产品主要使用 Impala 作为数据查询引擎,相比 Presto 等其他开源 OLAP 查询引擎,Impala 具有明显的性能优势。区别于社区版 Apache Impala,有数使用的是网易大数据的 Impala 增强版。


在有数大规模使用中,音乐等业务场景也呈现出了有数+Impala 的不少问题,包括查询错误较多、部分查询较慢等。针对这些问题,Impala 内核小组与业务、大数据产品团队合作进行了大量优化,提高了查询成功率,减少了慢查询数量。


后面我们会结合案例详细分析如何优化。开始前,先介绍优化所用的 2 个工具:


  • 在 Impala 这一侧,我们进行问题分析,寻找优化方法的主要工具是 Impala 管理服务器,这部分在下一小节展开介绍;

  • 另一个工具是有数报告。是的,我们用有数 BI 产品来对有数查询进行优化,将基于 Impala 管理服务器得到的分析结果制作成直观的图表报告。在优化过程也逐渐体会到有数产品的强大。

二、Impala 管理服务器

Impala 是个 Hadoop 生态下的 MPP 查询引擎,以性能著称,其核心组件包括 Catalog,Statestore 和 Impalad,Impalad 根据是否接收客户端查询请求又可分为 coordinator/executor。Impala 的系统架构如下所示:


社区版 Impala 运维上的不足

目前社区版 Impala 在运维方面还存在不少短板。主要体现在如下方面:


  • 社区版 Impala 为每个 coordinator 提供了 webui 界面,能够查看该 coordinator 正在执行和最近已完成的查询信息等。但 Impala 没有提供集群层面的查询视图,即没有将各 coordinator 节点的查询信息汇总到一个 webui 上。在观察集群查询状态时需要同时打开各个 coordinator 的 webui 并频繁切换;

  • coordinator 的 webui 上展示的查询信息是非持久化的,一旦进程重启,这些信息就丢失了,而上线升级、系统 bug 等因素,进程重启是不可避免的;

  • coordinator 的查询信息非持久化带来的另一个问题是:即使进程未重启过,其所能缓存的查询个数也是有限的,通过--query_log_size 参数进行配置;

  • coordinator 缓存的信息是在进程的地址空间内,未暴露出来。外部工具无法获取这些信息进行分析;

管理服务器功能

针对上述问题,网易大数据团队在 Apache Impala 社区版基础上开发了 Impala 集中式管理模块,即 Impala 管理服务器(managerd)。其主要功能包括:


  1. 汇总 Impala 集群中各 coordinator 节点正在执行和已完成的查询,提供统一的 web 端查询视图。这样在需要查找集群中正在执行或已完成的查询时,无需打开各 coordinator 的 web 界面;

  2. 将历史查询信息持久化到 MySQL 和对象存储上,有效防止进程重启或查询数量过多导致查询丢失问题;


管理服务器保存了集群上已执行的所有历史查询信息,包括查询基础信息表 basic_info 和查询明细表 detail_info,如下所示:



detail_info 相比 basic_info 的字段更少,但有多个 mediumblob 字段,其中包含了更丰富的查询信息。



detail_info 表有个 profile 字段,存储了 NOS 上的 key,该 key 对应的 NOS 对象保存了完整的查询 profile 文件。

profile 文件

profile 文件是深入分析查询整个执行过程的关键信息,包括查询的时间线(timeline),各个执行片段的 counter 信息、查询涉及的表是否有统计信息等。


三、使用痛点及优化

如前所述,我们可以把业务痛点分为慢查询和查询错误两类问题。下面就结合生产环境来举例说明具体存在哪些问题。

慢查询原因分析和优化

出现慢查询的原因很多,下面分别从 Impala、有数 BI 产品和 HDFS 等维度来进行说明。

1.Impala 相关

统计信息缺失


与主流的数据库和数仓查询引擎一样,Impala 也是基于代价模型进行执行计划优化(CBO)。只有获取足够的统计信息,才能支撑 Impala 选取较优的执行计划。


但 Impala 作为一个查询引擎,往往不负责 schema 的创建和数据的导入,因此,也就无法在数据导入时计算统计信息。作为一个基于 CBO 的查询引擎,若用户不手动执行 compute [incremental] stats 计算统计信息,Impala 的查询性能是要打折扣的。下图为统计缺失时的一个执行计划,可以看到 531.35G 的表分区作为右表被广播(broadcast)到集群的其他节点上进行 join 操作。




优化与改进


在对查询所涉及的表进行统计信息计算后,再次进行查询,join 方式变为分区模式(partitioned)。



优化效果是显而易见的,除了性能得到了提升(从 10 分钟超时变为 46s)。资源的消耗也急剧减低(详见 04:hash join 的 mem-estimate 值)。


因统计信息缺失导致的慢查询是普遍存在的,线上集群通过手动配置需要进行统计信息计算的表,对其跑 compute stats 脚本的方式来计算统计信息,作为临时的优化方式。


目前,我们已经依托 Impala 管理服务器开发了基于历史查询数据的自动统计信息计算功能,能够根据所配置的参数自动选择待处理的表,将其记录到 compute_stats_info 表中。



管理服务器通过后台线程读取这些表记录并进行统计信息计算。预计 Q1 上线使用。


元数据缓存未命中


除了基于 CBO 进行执行计划选择外,Impala 通过将表元数据缓存在本地来提升查询性能,如将 Hive 表的元数据从 Metastore(hms)加载到 Catalogd 和 coordinator 上,在为查询确定执行计划时就无需花时间通过 RPC 调用从 hms 获取所需的表元数据。


但由于 Hive 表会持续进行元数据更新,比如表分区的增加、删除和重命名,修改表属性等。这些都会导致 Impala 上缓存的元数据版本过旧,网易 Impala 版本增加了元数据同步功能,在 hms 侧有元数据更新时,会刷新(refresh table)或失效(invalidate metadata table)缓存的元数据。


问题原因及优化


元数据同步功能解决了元数据版本过低导致查询出错问题,但会失效缓存的元数据,导致性能下降。而且 Hive 表支持自定义属性,即用户可以增加一些具有特殊用途的表状态信息,比如网易大数据平台的元数据中心可为表增加访问次数等统计,举例如下。


'metahub.table.accessCount'='xxx',  'metahub.table.readCount'='xxx', 'metahub.table.readTimes'='xxx', 'metahub.table.referCount'='xxx', 
复制代码


元数据中心会调用 hms 的 alter table 接口以较高的频次更新这些信息(采样发现,在 15 分钟内,多达 191 次)。但其实,这些信息对于 Impala 并没有作用,不会对 Impala 执行计划产生影响。如前所述,alter table 操作会触发 Impala 侧缓存失效,导致查询时需重新加载。



上图所示为一个总执行时间 21.5 秒的查询,其中 11 秒花在从 hms 加载表元数据上。


在大数据开发团队的支持下,已能够识别这些对 Impala 没有影响的 alter table 操作并将其过滤掉,从而提高查询的缓存命中率。


目前仍有较多必要的 alter table 操作场景会导致元数据失效,比如每天的离线数据产出。下一步,我们计划通过优化元数据更新的方式,及时收集因为各种原因导致的元数据缓存失效掉,通过后台线程将其重新加载到缓存中。

2.有数 BI 查询相关

用户采用在有数界面拖拽控件的方式取数或制作图表,有数产品需要将其转换成 Impala 等查询引擎支持的 SQL 语句。有数生成的 SQL 是否合理,对查询性能具有重要的影响。下面列举 SQL 查询的优化案例。


问题举例


时间/日期转换导致性能问题


就公司内部而已,事实表的数据一般以时间作为分区字段,如每天一个分区,分区字段类型为字符串。在分析报告中,经常需要将时间字段转换为时间戳类型,或进一步截取为分钟、小时、天、周、月等粒度。如下所示:



诸如此类,需要对每条记录都一一进行多个时间转换处理操作,势必会影响查询的性能。下面是个是否进行时间转换的查询性能对比。



大查询拖慢 HDFS 扫描性能性能


HDFS 扫描性能往往会成为查询瓶颈,除了因与其他如离线分析等业务共用一套存储外,还有个原因是 Impala 下发了大量需扫描过多数据的查询语句。


有些业务表的单分区/天数据量超过 500G,某些有数查询的分区范围指定过大或没有指定分区,比如 1 个季度或干脆不限定分区,则单个查询至少需扫描 50+TB 数据量。下图就是个案例。



更加严重的是,对于像有数这种 BI 报表产品,同个报告可能会包含多张相似的报表,类似的查询往往都是成批出现的,影响更大。



产品侧优化


包括上述例子在内的多个 SQL 查询相关问题,在有数版本迭代过程中逐步得到了优化,比如下图为在有数 7.3 版本所做的 2 个优化。



3.HDFS 存储相关

该问题又可分为 2 种,分别是访问 HDFS NameNode(NN)获取文件元信息和从 DataNode(DN)读取文件数据。(需要注意的是,HDFS 瓶颈是相对的,分场景的。对于 Impala 查询来说可能是瓶颈,但对于离线批处理任务来说,可能同样的性能表现并不构成瓶颈)。本文主要讨论 DN 相关问题及优化。


小文件问题单文件过小,且文件数太多,导致无法通过顺序 IO 连续读取大数据块,需要重复走打开文件+读取数据的流程,效率较低;线上某些表存在较严重的小文件问题。如下所示例子,文件大小仅为 10+MB,线上个别表的文件大小甚至仅为 KB、Byte 级别。



分区过大一般情况下,数据扫描的最小粒度是分区级别,分区越大则需扫描的数据量大。下图所示某表,每天一分区,单分区文件数 1k+,分区大小 400+GB,共有 200+分区。也就是说,如果需要分析 1 个星期数据,需扫描近 3TB,若分析 1 个月,需扫约 15TB。



表存储格式 SQL On Hadoop 查询引擎查询 Parquet 或 ORC 格式的表文件时性能是最好的,如对 Impala 来说,对于 Parquet 或 ORC 格式,Runtime Filters(RF)特性的优势能够充分发挥,而对于 TEXT 文件格式,RF 仅能作用在分区表上。下图所示为一张 TEXT 格式的 100+G 非分区表,该集群每日慢查询中有不小比例与该表相关。



数仓治理


对于 DN 相关的性能问题,涉及数仓治理,目前主要依赖业务的数仓团队配合基于实际的业务场景进行优化。对于 TEXT 表,建议业务尽可能修改为 Parquet 格式。


对于小文件问题。首先应该合理配置数据生产/导入并发度,尽量减少小文件的产出的机率;其次,对于已存在的小文件,应在分区内进行适当的合并;再次,对于每个分区的总数据量过小的情况,应该考虑不对表进行分区。


对于分区过大问题。可考虑进行数据清洗提质,去除其中无价值的数据。据了解,音乐有 8 亿+用户,一般情况,会计算分析每个用户相关行为或推荐数据生成事实表,但这其中有一定比例的用户是不活跃的,甚至是多年未登录的。对于某些用户相关事实表,可以考虑去掉不活跃用户的数据,从而减少每个分区内的数据量。


同时,大数据平台将为业务提供小文件合并和文件格式转换等一键式数仓优化功能。

查询错误原因分析和收敛

业务在使用有数 BI 时会出现因为 Impala 侧查询错误导致取数结果或 BI 报告无法生成,严重影响有数产品的体验。业务反馈每天会有些查询出错,但不知道为什么出错,前端呈现的错误日志可读性差,因此也不知道该如何进行改进/优化。

1.错误分类

我们根据 basic_info 表的 state 字段获取出错(exception)的查询,并结合 detail_info 表的 status 逐步整理出了不同原因导致的错误。下面列举出现较多的错误。


SQL 自身错误


主要是 SQL 语法、参数限制和 UDF 误用等,举例如下:


org.apache.impala.common.AnalysisException: aggregate function not allowed in WHERE clause...org.apache.impala.common.AnalysisException: Exceeded the maximum number of child expressions (10000)....org.apache.impala.common.AnalysisException: No matching function with signature: default.dcount(BIGINT)
复制代码


元数据错误


主要包括无法打开文件、列类型不兼容、Parquet 格式不兼容、列未找到等,举例如下:


Disk I/O error on xxx.jd.163.org:22000: Failed to open HDFS file hdfs://hz-cluster11/user/da_music/hive/warehouse/xxxError(2): No such file or directory...Error: File 'hdfs://hz-cluster11/user/da_music/hive/warehouse/xxx' has an incompatible Parquet schema for column 'xxx'. Column type: STRING, Parquet schema:...org.apache.impala.common.AnalysisException: Could not resolve column/field reference: 't2.current_card'...org.apache.impala.common.AnalysisException: Failed to load metadata for table: xxx
复制代码


系统负载类错误


主要包括队列满、队列超时、SQL 内存超值、进程内存超值等错误。


Rejected query from pool root.default: queue full, limit=160, num_queued=165...Admission for query exceeded timeout 300000ms in pool root.default. Queued reason: queue is not empty (size 51); queued queries are executed first...Memory limit exceeded: Failed to allocate row batchEXCHANGE_NODE (id=31) could not allocate 16.00 KB without exceeding limit....Failed to increase reservation by 68.00 MB because it would exceed the applicable reservation limit for the "Process"
复制代码


查询被取消


错误提示很简单,有 Cancelled、Session closed 两种。均是产品侧主动 kill 了对应的 Impala 查询导致,可能原因有很多,我们目前主要关注因为执行时间超过阈值的查询,如音乐用的有数产品设置的阈值为 10 分钟,这些超时查询作为慢查询进行分析。

2.错误收敛优化

对于 SQL 自身错误,与上文所述 SQL 查询性能优化一样,主要与有数团队一起梳理对应的错误原因,改写有数 SQL 生成规则。


元数据错误


对于元数据错误,基本上是由于 Impala 元数据同步问题导致,举云音乐的有数 EasyFetch 集群为例。该集群在优化前存在较多因元数据同步导致的查询错误,以前的同学已初步定位到是由于 Impala 未同步通过“Impala 同步”选项开启的表元数据,但并没有继续分析为什么会无法同步。



在本次优化期间,我们从头梳理了一遍“Impala 同步”选项的功能和实现逻辑,确定是平台组件的代码 bug 导致,修复后此类错误大幅减少。


系统负载类错误


这是个综合性的问题,典型的场景是因为少数慢查询长期占用了系统资源。对于队列满、队列超时等错误,可以通过增加查询的并发数或排队超时时间来缓解,但提高查询并发数有可能会导致集群过载,查询性能进一步下降,反过来又会延长正在排队的查询的等待时间。另外一种可行的方式是直接向用户提示“当前系统负载过高,稍后再试”,避免用户在短时间内重复刷新页面导致情况恶化。


对于 SQL 内存或进程内存超值等错误,一般是由于复杂的大查询或对查询所需资源预估不准导致,对于前者,需要进行查询优化,比如减少数据扫描的范围等。对于后者,可通过补上表的统计信息来提高评估的精度。


系统负载类一般通过优化查询性能来解决。当然,如果一个集群每天都有好几个小时集中出现大量系统负载类错误,那么可以考虑是由于集群可用资源不够,应该及时扩容。

四、后续优化计划

经过大数据团队及业务的共同努力,网易云音乐、严选等业务的 Impala 集群在查询性能和错误收敛上取得了一定的成果,得到了音乐数仓团队的认可,达成了严选“双十一”确定的性能指标。


Impala 的性能优化仍在继续。下面简单例举正在做的事情。


  1. 全面替换公司内部业务的 Impala 集群版本,从 Impala 2.12 升级到 Impala 3.4 版本,提供更强大的功能特性和性能表现。目前已完成音乐 Impala 集群升级;

  2. 引入 Alluxio 作为 Impala 与 HDFS 间的缓存层;

  3. 基于历史查询信息的表统计信息自动计算功能;

  4. 基于物化视图(临时表)的 SQL 重写功能,通过创建预聚合表来优化查询性能;

  5. 与有数产品团队合作实施有数查询诊断项目。


作者简介:


温正湖,网易数帆数据库开发专家,10+年数据库和存储开发经验,2013 年加入网易杭州研究院,一直从事数据库开发相关工作,现为大数据产品部 OLTP&OLAP 数据库内核团队负责人,主要负责 MySQL、Impala 等内核特性设计和开发、落地使用以及问题定位;专注于数据库内核技术和分布式系统架构,乐于挑战和解决疑难问题;累计申请并授权 10+技术发明专利,《MySQL 内核:InnoDB 存储引擎 卷 1》作者之一。

2021 年 2 月 22 日 16:032111

评论 1 条评论

发布
用户头像
网易大数据的 Impala 增强版,会开源?
2021 年 02 月 23 日 10:08
回复
没有更多了
发现更多内容

ARTS Week17

时之虫

初学架构方法

Zzzz

极客大学架构师训练营

git 常用操作及 git 工作流介绍

hepingfly

git git分支操作 git工作流

架构师训练营1期-WEEK01-作业

Geek.Kwok

极客大学架构师训练营

第一周命题作业

王建军

架构师训练营-第一周命题作业

咖啡

ARTS打卡 第17周

引花眠

微服务 ARTS 打卡计划

第一周总结

_

极客时间 架构师 极客大学架构师训练营 第一周总结

极客时间架构 1 期:第 1 周架构方法 - 命题作业

Null

架构师训练营第一周总结

知鱼君

极客大学架构师训练营

# 架构师训练营Week1总结

lggl

极客大学架构师训练营 UML

week-1-part2 学习总结

陈龙

课程大作业

小胖子

# 架构师训练营Week1作业

lggl

极客大学架构师训练营

架构师第一周

Geek_Gu

极客大学架构师训练营

week1 架构方法总结

zero2onemore

我搭建了一套企业级私有Git服务,抗住了每天上万次攻击!

冰河

git 代码管理 代码仓库 私有服务 远程协作

第1周 作业

wgl

UML

架构师训练营第一周课程笔记及心得

Airs

「架构师训练营第 1 期」第一周作业 (作业二)

Geek_83908e

极客大学架构师训练营

Week_01学习总结

golangboy

极客大学架构师训练营

第一周:学习总结

王建军

第1周 作业

Pyr0man1ac

架构师训练营第 1 期第一次作业

Geek_a01290

极客大学架构师训练营

架构师训练营第 1 期第一周总结

Geek_a01290

极客大学架构师训练营

极客时间-架构师一期-第一周作业

_

极客时间 架构师 极客大学架构师训练营 第一周命题作业

week-1-part1 食堂就餐卡系统设计

陈龙

极客大学架构师训练营

架构师训练营学习笔记

Erwa

架构师第一周笔记

Geek_Gu

SpringBoot系列(1)-初识SpringBoot

引花眠

学习 springboot

【架构师训练营1期】第一周作业

诺乐

基于Impala的网易有数BI查询优化总结-InfoQ