经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Spark » 查看文章
使用spark-sql处理Doris大表关联
来源:cnblogs  作者:相由心生,命由己造  时间:2024/6/12 18:07:17  对本文有异议

背景

最近项目上有一个需求,需要将两张表(A表和B表)的数据进行关联并回写入其中一张表(A表),两张表都是分区表,但是关联条件不包括分区字段。

分析过程

方案一

最朴素的想法,直接关联执行,全表关联,一条SQL搞定全部逻辑。想法越简单,执行越困难。由于数据量大,服务器规模较小,尽管各台服务器内存和CPU配置都很高,关联会将数据读取到内存,内存根本放不下,而且集群配置了workload group,可使用内存更小了,方案一不可行。

方案二

可以在关联时增加分区字段对任务进行拆解,这样可以实现,但是会形成笛卡尔积,历史数据量巨大,分区较多(A表和B表都是1年),缺点也很明显。

  • 执行耗时长
  • 执行语句太多,操作不便
  • 如果按照单分区关联,A表的每一个分区将会扫描B表全表

经过评估上述方案二不可行。

方案三

通过外部计算和存储来实现,可选的有Hive、Spark、Flink。三种方案都是可行的,但是从操作复杂度来看使用spark-sql直接读取Doris进行关联并写回Doris,除DDL外,只需要一条SQL即可搞定。

详细过程

  1. 下载预编译的spark和spark-doris-connector
  1. 部署
    将上述安装文件上传至Hadoop集群的其中一台机器,放置到任意目录,比如/opt,请保证使用的用户可以向Yarn提交任务。
    解压缩spark-3.4.3-bin-hadoop3.tgz得到spark-3.4.3-bin-hadoop3目录
    将spark-doris-connector-3.4_2.12-1.3.2.jar放到spark-3.4.3-bin-hadoop3/jars/

  2. 启动spark-sql

  1. bin/spark-sql --master yarn --num-executors 40 --executor-memory 7G --name Spark-SQL:Doris
  1. 创建映射表
  1. -- 用于读取A表数据
  2. CREATE
  3. TEMPORARY VIEW spark_doris_a
  4. USING doris
  5. OPTIONS(
  6. "table.identifier"="mydb.table_a",
  7. "fenodes"="10.*.*.1:9030,10.*.*.2:9030,10.*.*.3:9030",
  8. "user"="root",
  9. "password"="$YOUR_DORIS_PASSWORD"
  10. );
  11. -- 用于读取B表数据
  12. CREATE
  13. TEMPORARY VIEW spark_doris_b
  14. USING doris
  15. OPTIONS(
  16. "table.identifier"="mydb.table_b",
  17. "fenodes"="10.*.*.1:9030,10.*.*.2:9030,10.*.*.3:9030",
  18. "user"="root",
  19. "password"="$YOUR_DORIS_PASSWORD"
  20. );
  21. -- 用于向A表部分列写入数据
  22. CREATE
  23. TEMPORARY VIEW spark_doris_a_sink
  24. USING doris
  25. OPTIONS(
  26. "table.identifier"="mydb.table_a",
  27. "fenodes"="10.*.*.1:9030,10.*.*.2:9030,10.*.*.3:9030",
  28. "user"="root",
  29. "password"="$YOUR_DORIS_PASSWORD",
  30. "sink.properties.partial_columns"="true",
  31. "sink.properties.column"="'column_a','column_b','column_c'"
  32. );
  1. DML语句
  1. set enable_unique_key_partial_update=true;
  2. set enable_insert_strict=false;
  3. insert into spark_doris_a_sink
  4. (column_a,column_b,column_c)
  5. select a.column_a,b.column_b,b.column_c from spark_doris_a a left join spark_doris_b b on a.colum_d = b.column_e;

遇到的问题

处理过程很简单,但是实际也是遇到了很多问题

  1. DML语句中不能使用分区字段进行过滤,因为Doris 2.0版本在提供的获取执行计划的API中对于引号的处理存在问题,如果传递的是"2024-06-12",则会得到数值2006,该数值无法转换为日期,如果传递"20240612"也无法得到Date("20240612")。理论上,如果调整此处的写法增加嵌套的引号配合转义字符也能实现功能,Java程序员都懂的,有兴趣可以自行验证。
  2. spark executor 内存和并行度设置,这个需要不断调整,我也是尝试了多次,才得到这个可以运行的结果。并行度设置太高了,将会对Doris形成较大的网络和IO冲击,一定要慎重。并行度低了,内存就要高一点,不然数据都已经从Doris读取出来了,关联的时候会内存溢出。
  3. 读取Doris的速率还是很快的,而且spark在读取doris前获取了执行计划,对数据进行了行和列的裁剪,不会将整表数据都读出来。

原文链接:https://www.cnblogs.com/aaronking/p/18243535

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号