【问题标题】:Best Practice to migrate data from MySQL to BigQuery将数据从 MySQL 迁移到 BigQuery 的最佳实践
【发布时间】:2017-06-06 01:36:36
【问题描述】:

我尝试了几种 csv 格式(不同的转义字符、引号和其他设置)从 MySQL 导出数据并将其导入 BigQuery,但我无法找到适用于所有情况的解决方案。

Google SQL requires 以下代码用于从/向 MySQL 导入/导出。虽然 Cloud SQL 不是 BigQuery,但它是一个很好的起点:

SELECT * INTO OUTFILE 'filename.csv' CHARACTER SET 'utf8' 
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '' FROM table

目前我使用以下命令将压缩的 csv 导入 BigQuery:

bq --nosync load -F "," --null_marker "NULL" --format=csv PROJECT:DATASET.tableName gs://bucket/data.csv.gz table_schema.json

一方面,bq 命令不允许设置转义字符(" 被另一个" 转义,这似乎是一个定义明确的CSV 格式)。另一方面,\" 作为 MySQL 导出的转义字符会导致 "N 作为 Null 值,这也不起作用:

CSV table references column position 34, but line starting at position:0 contains only 34 columns. (error code: invalid)

所以我的问题是:如何在 SQL 中为 MySQL 编写(与表无关的)导出命令,以便可以将生成的文件加载到 BigQuery 中。应该使用哪个转义字符以及如何处理/设置空值?

【问题讨论】:

  • 是否将 --null_marker 设置为“N 工作?
  • @Tianzhou 我试过--null_marker to "\"N" 没有成功。

标签: mysql csv google-bigquery


【解决方案1】:

2019 年更新:

试试这个作为替代方案:

  • 将 MySQL 备份文件加载到 Cloud SQL 实例中。
  • 直接从 MySQL 中读取 BigQuery 中的数据。

更长的操作方法:


您可以使用mysql2xxxx 之类的工具在导出时获得最大的灵活性。

使用mysql2csv,您可以运行任意查询,并且输出过程利用FasterCSV,这将为您提供比现有mysql 更多的选择。

【讨论】:

  • 很好,感谢您的链接!我开始写自己的工具直接将数据从mysql导出到bq,但我会尝试一下。
  • 我试过了,但对于我的用例来说太慢了。它已经运行了 6 小时,并且只导出了表的一小部分。
  • 仅供参考,原生方式需要多长时间?
  • 尝试通过 Cloud SQL 作为替代方案:medium.com/google-cloud/…
【解决方案2】:

你可以试试sqldump-to。它读取任何与 MySQL 兼容的转储流并输出以换行符分隔的 JSON,以便轻松导入 BigQuery。

CSV 或 TSV 的问题在于转义字符。 JSON 没有这个问题。

该工具还支持架构导出,之后需要使用每列特定的 BigQuery 数据类型对其进行编辑,但这是一个有用的开端。

例如,使用mysqldump 流入sqldump-to

mysqldump -u user -psecret dbname | sqldump-to --dir-output ./dbname --schema

您可能需要修改 mysqldump 命令以匹配您的特定 MySQL 配置(例如远程服务器等)

如果您已经有转储文件,该工具还支持多个工作人员以更好地利用您的 CPU。

sqldump-to 创建您的 JSON 文件后,只需使用 bq 命令行工具加载到 BigQuery:

bq load --source_format=NEWLINE_DELIMITED_JSON datasetname.tablename tablename.json tablename_schema.json

【讨论】:

    【解决方案3】:

    A MySQL Table to BigQuery Import Script.md 会将 MySQL 表或完整架构导出到 Big Query。

    mysql_table_to_big_query.sh 将表从 MySQL 导出为 CSV,并将架构导出为 JSON 和 SQL 文件。然后将文件上传到云存储桶的文件夹中。然后将这些文件导入到大查询中。 BigQuery 数据集在同一个项目(如果不存在)中创建,名称为 {SCHEMA_NAME}_{DATE}。 如果该表具有数据类型 DATE 的列,则该表在 BigQuery 中进行分区。

    mysql_schema_to_big_query.sh 从 MySQL 模式中提取所有表的列表,并为每个表调用 mysql_table_to_big_query.sh。 该脚本创建 csv 文件,根据需要翻译空值。然后它将它们转移到现有的谷歌存储并导入到大查询中。

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,从 MySQL 导入到 Big Query,并且由于我的数据集包含多个文本列,我无法使用标准分隔符,例如 , ;甚至 \t 没有包围。

      但是对于 encloser,我遇到了默认 \ 转义符的转义双引号问题,或者 " 转义符的空值问题,它变成了 "N 而不是 \N。

      我能够通过使用以下步骤和配置使其工作。诀窍是使用control character 作为安全分隔符,因为我确信我的数据中没有这样的字符。

      第 1 步:从 MySQL 导出

      配置:

      • 字段分隔符:控制字符 001
      • 附件:''(无)

      这是完整的 MySQL 查询。我使用的是 AWS RDS Aurora,所以语法与标准 MySQL 略有不同(文件写入 S3):

      SELECT * FROM my_table
      INTO OUTFILE S3 's3://xxxxx/tmp/my_table/data'
      CHARACTER SET UTF8MB4 
      FIELDS TERMINATED BY x'01'
      OPTIONALLY ENCLOSED BY ''
      MANIFEST OFF 
      OVERWRITE ON
      

      第 2 步:使用 gsutil 将数据集复制到云存储

      gsutil rsync -m s3://xxxxx/tmp/my_table/ gs://xxxxx/tmp/my_table/
      

      第 3 步:使用 CLI 在 Big Query 上加载数据

      bq load --source_format=CSV --field_delimiter=^A --null_marker="\N" --quote="" project:base.my_table gs://xxxxx/tmp/my_table/* ./schema.json
      

      注意事项

      • ^A 是控制字符的表示。您可以在 Windows 上通过键入 Alt+001 来创建它,在 linux shell 上使用 Ctrl+VCtrl+A(更多信息 here )。实际上只是一个字符。
      • 我们无法使用 Web 界面创建表格,因为我们无法将控制字符定义为分隔符。

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题,这是我的解决方案:

        从 MySQL 导出数据

        首先,以这种方式从 MySQL 中导出数据:

        SELECT * INTO OUTFILE 'filename.csv' CHARACTER SET 'utf8' 
        FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '' 
        FROM table <yourtable>
        

        这实际上是一个 tsv 文件(制表符分隔值),但您可以按照 csv 的想法将它们导入。

        导入 Big Query

        ​​>

        这样您应该可以使用以下命令将其导入到大查询中 参数:

        bq load --field_delimiter="\t" --null_marker="\N" --quote="" \
        PROJECT:DATASET.tableName gs://bucket/data.csv.gz table_schema.json
        

        注意事项

        1. 如果您的 MySQL 数据库中的任何字段包含制表符 (\t),它将破坏您的列。为防止出现这种情况,您可以在列上添加 SQL 函数 REPLACE(&lt;column&gt;, '\t', ' '),它将从制表符转换为空格。

        2. 如果您在大查询的 Web 界面中设置表架构,则无需在每次加载 CSV 时都指定它。

        我希望这对你有用。

        【讨论】:

        【解决方案6】:

        使用以下 SQL 命令似乎对我有用,使用 \N 生成空值:

        SELECT * INTO OUTFILE '/tmp/foo.csv' CHARACTER SET 'utf8'  
        FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY "\\" 
        FROM table;
        

        有了这个,您应该可以使用--null_marker="\N" 导入数据。您可以试一试,如果它不适合您,请告诉我?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-01
          • 2023-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-05
          相关资源
          最近更新 更多