Массовая миграция данных через Spark SQL
в настоящее время я пытаюсь выполнить массовую миграцию содержимого очень большой таблицы MySQL в файл parquet через Spark SQL. Но при этом у меня быстро заканчивается память, даже при установке предела памяти драйвера выше (я использую spark в локальном режиме). Пример кода:
Dataset<Row> ds = spark.read()
.format("jdbc")
.option("url", url)
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", "bigdatatable")
.option("user", "root")
.option("password", "foobar")
.load();
ds.write().mode(SaveMode.Append).parquet("data/bigdatatable");
похоже, что Spark пытается прочитать все содержимое таблицы в память, что не сработает очень хорошо. Итак, каков наилучший подход к массовой миграции данных через Spark SQL?
1 ответов
в вашем решении Spark будет считывать все содержимое таблицы в один раздел до начала записи. Один из способов избежать этого-разбиение части чтения, но для этого требуется числовой последовательный столбец в исходных данных:
Dataset<Row> ds = spark.read()
.format("jdbc")
.option("url", url)
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", "bigdatatable")
.option("user", "root")
.option("password", "foobar")
.option("partitionColumn", "NUMERIC_COL")
.option("lowerBound", "1")
.option("upperBound", "10000")
.option("numPartitions", "64")
.load();
в приведенном выше примере столбец "NUMERIC_COL" должен существовать в данных, и в идеале он должен равномерно варьироваться от 1 до 10000. Конечно, это много требований, и такой столбец, вероятно, не будет существовать, поэтому вы должны вероятно, создайте представление в базе данных с таким столбцом или добавьте его в запрос (обратите внимание, что я использовал общий синтаксис SQL, вам придется адаптироваться к вашей СУБД):
String query = "(select mod(row_number(), 64) as NUMERIC_COL, * from bigdatatable) as foo"
Dataset<Row> ds = spark.read()
.format("jdbc")
.option("url", url)
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", query)
.option("user", "root")
.option("password", "foobar")
.option("partitionColumn", "NUMERIC_COL")
.option("lowerBound", "0")
.option("upperBound", "63")
.option("numPartitions", "64")
.load();