Массовая миграция данных через 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();