MySQL的数据如何通过外键关系导入HDFS和split/partition/distribute的数据?

How to import data from MySQL to HDFS and split/partition/distribute data by foreign key relations?

我是 HDFS 和 Spark 的新手。我有一些特定于区域(可能是国家或国家的一部分)和时间函数的模拟的输入数据。

假设我有以下表格:

region:
id, name

-

population:
id, region_id, year_2020, year_2021, .... year_2050

-

sun_hours:
id, region_id, year_2020, year_2021, .... year_2050

(实际情况比较复杂,嵌套实体和外键关系较多)

我想将所有数据从 MySQL 导入到 HDFS 并按 region_id 分区。

理想情况下,我集群的每个节点都负责一个区域,这样我就可以轻松地并行处理这些区域。如果我想考虑更多区域,我可以通过添加更多节点来 缩放模拟 。 (我的模拟的一个基本假设是区域之间不相互作用)。

我希望在模拟过程中,数据不需要在节点之间传递,因为一个特定区域所需的所有数据已经​​位于一个节点上具体节点。如果在 splitting/distribution 的过程中有一些数据重复,对我来说是可以的。我预计单个区域的模拟要求很高,以至于单个节点可能不想并行计算多个区域。

我找到了一个 sqoop 命令来导入几个表 到 hdfs:

sqoop import-all-tables --connect jdbc:mysql://db.foo.com/corp

https://sqoop.apache.org/docs/1.4.2/SqoopUserGuide.html#_literal_sqoop_import_all_tables_literal

但是,我发现无法指定数据应该如何分区和分布。该过程应该考虑一些 "main entity" (= region).

我可以用 sqoop 这样做吗?如果是,能否提供一个示例命令?

如果没有,是否有其他工具可用于我的目的?

如果我需要自己做,你会推荐给

a) 首先导入所有数据,然后重新组织或

b) 首先重组数据并将其写入例如区域特定的文本文件,然后将其导入 HDFS?

即使我设法重组了(分层的)MySQL 数据,我如何才能确保所有相关数据都可以在单个节点 上找到,而不是分散在整个集群中?

与其他作品一起使用:hdfs、spark 或其他一些大数据工具是否具有将相关内容放在一起的功能?可以说我有一些包含人口的 RDD 和一些包含日照时间的 RDD。 区域 1 的人口和日照时数应位于节点 x... 区域 2 的人口和日照时数应位于节点 y 上,依此类推。

(为了减少出错,这很好,我想需要...在多个节点上复制数据。我只想确保在没有节点问题的模拟期间,节点之间的流量越低越好。)

编辑

我刚找到 GeoSpark,它指出

GeoSpark spatial partitioning method can significantly speed up the join query. Three spatial partitioning methods are available: KDB-Tree, Quad-Tree and R-Tree. Two SpatialRDD must be partitioned by the same way.

If you first partition SpatialRDD A, then you must use the partitioner of A to partition B.

objectRDD.spatialPartitioning(GridType.KDBTREE) queryWindowRDD.spatialPartitioning(objectRDD.getPartitioner)

https://datasystemslab.github.io/GeoSpark/tutorial/rdd/

所以也许我应该尝试将我的 MySQL 数据库转换为与 GeoSpark ("can be loaded from CSV, TSV, WKT, WKB, Shapefiles, GeoJSON and NetCDF/HDF format") 兼容的格式。

相关文章:

sqoop(不是 Spark)对于 tables 更是如此。它可以使用视图,但据说对于复杂的视图,结果甚至可能不可靠。所以,那条大道是封闭的。

您将需要使用 spark.read JDBC 与 mySQL 中的视图的连接,该视图使用 region_id 作为分发的关键 - 为了您的并行性 - 使用 numPartitions "driving" table 上定义的方法。与其他 table 的连接需要依赖 mySQL 引擎。

我不知道你的处理过程,但似乎很难强制执行 1 对 1 region_id 分区方法。此外,同一节点上可能存在 1 个以上的分区 - 但独立。

您可以独立获取所有 table,然后加入,但会出现混洗,因为无法保证所有单独的 READ 结果最终都在同一节点上。