前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spark sql简单查询千亿级库表导致的问题

spark sql简单查询千亿级库表导致的问题

原创
作者头像
mikealzhou
修改2018-12-19 23:42:28
5.1K0
修改2018-12-19 23:42:28
举报
文章被收录于专栏:大数据平台TBDS

一、问题现象

今天有客户咨询到我们,他们利用spark sql查询简单的sql:

代码语言:javascript
复制
select * from datetable limit 5; //假设表名是datetable

结果报错内存溢出:

客户反馈spark sql简单查询内存溢出
客户反馈spark sql简单查询内存溢出
报错详情
报错详情

根据常理判断,简单的 select * limit 不会造成内存溢出的。因此,我们用hive原生sql查询,发现不存在这个问题。

二、排查问题

经过分析,发现被查询的表数据量特别大,整个表有1000多亿行数据。一般这种海量数据大型数据表,往往是做了多重分区的。

经过查看,发现被查询的数据表是双重分区表(也就是有两个分区字段)。dt是第一个分区字段,表示天; hour是第二个分区字段,表示小时。数据表存储在HDFS的目录结构也是:

代码语言:javascript
复制
/${hive-warehouse}/dbname/tablename/dt=xxx/hour=xxx/files

根据之前使用spark sql的经验、以及逛社区查找的信息,最终找到原因如下:

因为 datetable 这个表是一个双重分区表,即使进行 select * limit 也至少会进行第一重分区的完整数据扫描。因此,对于双重分区表,需要加上双重分区条件(或者至少加上第一重分区条件),然后再进行 select * limit 查询。比如:

代码语言:javascript
复制
select * from datetable where dt='2018-11-14' and hour='07' limit 5;

或者至少把第一重分区条件加上:

代码语言:javascript
复制
select * from datetable where dt='2018-11-14' limit 5;

不能直接用 :

代码语言:javascript
复制
select * from datetable limit 5;

这种语句spark sql至少会扫描一个完整的第一重分区的数据,当数据量很大的时候,因此往往会出现内存不足。因为datetable有1000亿行数据,单个的第一重分区的数据量往往也是超过TB级别的。因此,如果全量扫描TB级别数据到有限数量的excutor内存里面去,肯定会出现内存不足。

三、验证结论

1、首先我们直接用spark sql查询:

代码语言:javascript
复制
select * from datetable limit 5;

从日志可以查看出excutor在疯狂地扫描HDFS的文件:

而且这些被扫描的HDFS文件,确实属于表的某个第一重分区的目录。日志证明刚才的推断是正确的。

2、加上第一重分区条件:

代码语言:javascript
复制
select * from datetable where dt='2018-11-14' limit 5;

很快就返回结果。

3、加上第一重和第二重分区条件:

代码语言:javascript
复制
select * from datetable where dt='2018-11-14' and hour='07' limit 5;

毫秒级就出结果。

因此,经过验证,上述分析完全正确。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、问题现象
  • 二、排查问题
  • 三、验证结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档