sql常见报错之 Data skew for single key found

  其他常见问题
内容纲要

问题说明


报错信息:Data skew for single key found. key content : […] has too many values. Values exceed safety size : 536870912(536870994)

顾名思义,因为某些值过多导致数据倾斜,本文给出相关解释说明及解决方案。

故障排查


涉及到一个参数,ngmr.safety.size.single.entry,默认值 536870912,单位byte。 表示单个task内相同key对应的value的数据量达到了512M 的上限,判定为数据倾斜。

以下图为例,liang两张表left join 时报错 Data skew for single key found. key content : [1,49,50,54,56,54,54,55,57,0] has too many values. Values exceed safety size : 536870912(536870994)

从DBAService Query页面DAG也能看到时两个表的common join阶段。

查找集中的joinkey的方法:

sql方式,可以参考 sql常见报错之 bucket size is too large (>2G) after compress 中提到的三种方法。

这里我们对左右两表 分别聚合查询 统计出两边joinkey的数量:

--左表:
SELECT A1.ACCOUNT_ID,COUNT(*) 
FROM ODSCRM.PLATFORM_ENS_D_ACCOUNT_MERGE A1 
WHERE A1.IS_BALANCE='Y' 
GROUP BY A1.ACCOUNT_ID 
ORDER BY 2 DESC 
LIMIT 20;

--右表:
SELECT A3.ACCOUNT_ID,COUNT(*) 
FROM ODSCRM.PLATFORM_ENS_F_ENTRY_MERGE A3 
GROUP BY A3.ACCOUNT_ID 
ORDER BY 2 DESC 
LIMIT 20;

可以看到右表A3,在 joinkey A3.ACCOUNT_ID='12686679'时,倾斜较为严重,有29082901条重复数据。

这里再提供一种姿势,根据报错byte数组直接解析出倾斜key的值。

借助java代码,实现 将字节数组(byte[])转换为 UTF-8 编码的字符串

import java.nio.charset.StandardCharsets;
public class byte2stringREAL {
    public static void main(String[] args) {
        byte[] bytes = new byte[]{1,49,50,54,56,54,54,55,57,0};
        System.out.println("Text : " + bytes);
        String s = new String(bytes, StandardCharsets.UTF_8);
        System.out.println("Output : " + s);
    }
}

也能够得到 12686679 这个值。

解决方案


首先让客户判断sql的业务逻辑是否合理(比如笛卡尔积),倾斜的joinkey数据是否异常(比如没有做数据清洗)…

如果都确认没有问题的话,可以尝试下面的解决方案:

方案一:set ngmr.safety.size.single.entry=-1,放开限制

仅限session级使用 临时workaround,不可以全局配置。

方案二:mapjoin

参考官网使用手册 Inceptor Mapjoin 使用说明):

方案三:skewjoin

参考官网使用手册 ArgoDB SKEWJOIN 使用说明):

这篇文章对您有帮助吗?

平均评分 0 / 5. 次数: 0

尚无评价,您可以第一个评哦!

非常抱歉,这篇文章对您没有帮助.

烦请您告诉我们您的建议与意见,以便我们改进,谢谢您。