ITPub博客

首页 > 数据库 > 数据库开发技术 > 面对一个20G的json文件,Doris的解决方案有哪些?

面对一个20G的json文件,Doris的解决方案有哪些?

原创 数据库开发技术 作者:安瑞哥是码农 时间:2024-05-23 21:47:05 0 删除 编辑


如果说前面几次用 Doris 基于 json 数据提供的解决方案,只能算比较片面的功能性测试的话,那么这一次,咱就针对一个更加具体的,较大数据文件的存储和查询需求。


看 Doris 可以提供哪些较为完整的解决方案?


从流程上来说,一个数据文件,想要完成从「原始态」,到「可被查询态」的转变,有两个步骤需要走:


第1个:选择合适的数据导入方式;


第2个:设计合理的表结构,来承载后续的查询。


那么接下来,我们就根据这两个步骤,来分别检验 Doris 这款数据库,在面对一份20G的 json 数据文件时,分别在导入跟查询时,能提供的解决方案。



0. 确定需求


就是这么一份 schema- free 的数据文件,里面的每一行,都是一个 json,内容大概长下面这样:



说起来,相比之前几期测试用的 json,这次的结构要更简单一点,不再出现 json array 里,再次包含 json 对象的情况。


总大小为 20G,数据行数为2千万,也就是说,每条 json 大小平均约为 2MB。


json 文件总大小


json 文件总条数


对于这份数据的存储,从往前的测试结论来看,存为 Doris 的 variant 类型最为合适。


而至于数据的导入方式,则有下面几种。



1. Doris 提供的 json 文件导入方式


几乎翻遍了 Doris 的官网,目前发现了 2 个靠谱、简单、不需要编码的方式。


1.1 直接的 json 导入方式



这种方式应该是目前为止,最简单的导入方式了(stream load),根据目前表的表结构:


CREATE TABLE `domain_whois_variant` (
  `domain` VARCHAR(100) ,
  `detail_json` VARIANT,
  `create_time` DATETIME 
)UNIQUE KEY(`domain`)
DISTRIBUTED BY HASH(`domain`) BUCKETS 3
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
); 


那么对应的 json 文件,跟这张表中3个字段的映射关系设置,就是这样的:


-H "format: json" 
-H "jsonpaths: [\"$.sld\", \"$.whois\", \"$.whois.createddate[0]\"]" 
-H "columns: domain, detail_json, create_time"


完整的导入命令就是:


curl -v --location-trusted 
-u root:xxx 
-H "timeout: 3000" 
-H "read_json_by_line: true" 
-H "format: json" 
-H "jsonpaths: [\"$.sld\", \"$.whois\", \"$.whois.createddate[0]\"]" 
-H "columns: domain, detail_json, create_time" 
-T floattop2kw_whois.json http://192.168.221.173:8030/api/whois_db/domain_whois_variant/_stream_load


虽然上面这些整挺好,但是,命令一运行起来就嗝了:



提示导入文件过大。


那么根据官方文档的解决办法,就是调参数喽。



既然这样,那就调大一点(40G总可以了吧):



因为集群有3个 BE,所以对应需要执行3个这样的命令。


你别说,你还真别说,这样子好像真的就可以了。



2千万条 json 数据,全部导入成功,耗时为 5分19秒。


这里有个需要注意的地方:


那就是在取这个 json 内部 key createddate 的值时候,如果你指定的 json 路径为 $.whois.createddate,而因为它的值是一个 array,数据是取不出来的(为NULL,按道理说不应该)。



只能改为 $.whois.createddate[0]。


1.2 Broker Load 读取 HDFS 的方式


这种方式相比上面,操作步骤上要稍微麻烦一点,比如需要将数据上传到分布式文件系统 HDFS。



而这种需要提前把数据上传到分布式文件系统,是使用 Broker Load 的前提。



还记得上一次,我用过这种方式把一个8亿+条数据的 Doris 表,给导出到 HDFS,当时因为导出数据量太大,需要手动调整导出时,BE 读数据超时的参数,否则是导出不成功的,不知道这一次也需不需要调整。


首先,把 json 文件上传到 HDFS。



然后,找到官网给的,json 数据的导入案例。


官网提供的导入案例


依葫芦画瓢,编一个我自己的导入任务:


LOAD LABEL whois_db.label001
(
    DATA INFILE("hdfs://192.168.211.106:8020/DATA/2kw_whois/floattop2kw_whois.json")
    INTO TABLE `domain_whois_variant01`
    FORMAT AS "json"
    (domain, detail_json, create_time)
    PROPERTIES(
      "jsonpaths" = "[$.sld, $.whois, $.whois.createddate[0]]"
    )       
)
with HDFS
(
  "fs.defaultFS"="hdfs://192.168.211.106:8020",
  "hadoop.username"="hdfs"
);


但是,这个瓢,好像画失败了。


查看导入任务的状态时发现,



这个导入任务,它压根就跑不起来。


一直就告诉你这个 json 路径映射有问题。


我就奇了怪了,这个导入配置,不是照着官方文档的模板抄过来的嘛,咋球不行了呢?


大概盯着这个配置发呆了得有2分钟,也不知道为什么,突然灵光一闪,我就把原本的这个地方:


"jsonpaths" = "[$.sld, $.whois, $.whois.createddate[0]]"


给改成了这个:


"jsonpaths" = "[\"$.sld\", \"$.whois\", \"$.whois.createddate[0]\"]"


然后就可以了。就问如果是你,你想不想骂人(写文档的同学,可上点心吧)?



虽然导入过程没有上一个 stream load 的方式方便,但这个效率明显要更高一些,总耗时2分钟半,效率是 stream load 的2倍多,而且不需要调整任何导入参数。


1.3 暂时没有发现


剩下的就要更麻烦一些了,算球,不试了。



2. 导入结果


先来看一眼这两种分别用 stream load,以及 broker load 方式导入到数据库中表的大小。


两种导入方式导入的数据量


两种方式导入的数据大小


可以看到,20G的原始数据,入库之后,在没有添加任何额外索引的情况下,存储占用只有大概原数据的1/5。


再看一眼写入数据后的表结构:



字段数量由原来的3个,变成了现在的 N 多个(后面还有,没有截全)。


而且可以看到,这里面有很多从 json 中提取出来的新字段都是 Array,但是对于 Doris 来说,官网对于 Array 这个数据类型的功能描述,几乎没有。


这就导致我想要对这些从 json 提取出来的子字段进行条件查询时,不能像其他普通字段一样那样自由。


比如,我虽然可以这样查:



但如果我把查询条件再限制苛刻一点。



发现就不行了。


综合上次对 variant 的功能测试结论,还是那句话,对于这个数据类型的功能优化,还有待进一步加强。



最后


从这次将一个20G的 json 文件,导入到 Doris 带 variant 类型字段的表需求出发,测试了两种(stream load + broker load)将文件数据,导入到表中的方法。


其中相同点:


1. 两种方法都能满足较大文件数据的导入;


2. 导入效率都还比较高。


不同点:


1. stream load 方式更简单,对导入要求更低,但默认导入文件大小比较小,如果是大文件,需要调整导入参数;


2. broker load 方式,需要将文件先上传到分布式文件系统(比如 HDFS、S3),才能使用,导入效率更高一些,且不用调整参数。


另外,虽然这次导入的数据,json 格式没有之前的复杂,但从查询体验来看,variant 的表现依然有瑕疵,还有进一步优化的空间。




你可以添加我的私人微信,拉你入技术讨论群,跟一群热爱技术的小伙伴一起成长...


原文作者:安瑞哥是码农;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-02-16

  • 博文量
    228
  • 访问量
    115417