您对如何在具有 10K+ 列的表上加速 Spark-SQL 有什么建议吗?
TL;TR: . 我必须解决 spark-SQL 处理具有来自 ORC 文件的 10K+ 列的宽表的性能问题。我注意到了这种改进 /CR:https://issues.apache.org/jira/browse/SPARK-25643
Spark 架构旨在处理长而窄的数据(<1K cols),这与我们这里的 = 10K 列 - 宽且相对较短的输入相反。
建议的解决方案:
简单:而不是 10K+ 列上的一个大 SQL - 创建多个 SQL - 在临时表中输出 - 然后从临时表连接/联合到最后一个。
SPARK:“解决者/计划构建者”——不确定我是否正确命名,需要进一步调查。我运行这个测试:
val n = 1000
val values = (1 to n).map(_.toString).mkString(", ")
val columns = (1 to n).map("column" + _).mkString(", ")
val query = s" SELECT $columns FROM VALUES ($values) T($columns) WHERE 1=2 AND 1 IN ($columns) GROUP BY $columns ORDER BY $columns".stripMargin
spark.time(spark.sql(query))
输出:
列 | 预期线性 [ms] | 真实 [毫秒] | 真实 [分钟] |
---|---|---|---|
100 | 200 | 183 | 0.003 |
250 | 500 | 306 | 0.005 |
500 | 1000 | 524 | 0.009 |
1000 | 2000 | 1514 | 0.025 |
2500 | 5000 | 7922 | 0.132 |
5000 | 10000 | 31131 | 0.519 |
10000 | 20000 | 134429 | 2.240 |
12500 | 25000 | 200568 | 3.343 |
15000 | 30000 | 348068 | 5.801 |
20000 | 40000 | 595804 | 9.930 |
尝试从 O(N^2) => O(N) ..
SPARK:自动分离器 - 在火花管道中引入 2 个新阶段:
- 语法拆分器 - 在开始时,即:更改“联合”行为 - 拆分为单独的 SQL,或更高级 - 处理 SQL,将列分成组:A - 参与转换(数学等的一部分),B - 不转换,然后创建多个列数较少的 SQL
- 最后从那些较小的 SQL 中输出混合器(连接/联合)。
TODO:寻找开销:过于复杂的计算/结构,计划中的新阶段等。
- 框外命题 [3rd party],例如:H2O with ORC parser
H2O 有自己的 DF 表示 - 由 Cliff Click 完全重写。H2O 支持 xxK+ 列。H2O 计算 - 低级 - 无 SQL。期望:相当高 - H2O 被设计为使用 WIDE 列,并且列转换非常高效 - 它们有自己的索引机制等。
开箱即用的命题:DB 和使用 DBA 解决问题
开箱即用:noSQL,因为它是为宽列设计的
Spark 命题相当大/影响现有的 SQL 功能——不能保证这在将来会起作用。
PoC plan:
1. Create: 3 tables - one with 10K columns
2. SQL that contains 3+ unions, 5+calculations
3. Multi SQLs 3+ (splitting unions) +1 final JOIN
3. Compare timing 2. and 3.
注意:这个 PoC 可能是火花分离器解决方案的一个足够好的指标。期望:假设当前时间是指数 => 更改为时间的总和,一切都将取决于最终的连接(不应该有任何其他操作)。
否则,基本上,我在泡菜:请任何建议如何解决这个问题。