将数据从MySQL迁移到BigQuery的最佳实践

时间:2017-01-20 23:58:08

标签: mysql csv google-bigquery

我尝试了几种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-command不允许设置转义字符("被另一个"转义,这似乎是一个定义良好的CSV - 格式)。另一方面\"作为MySQL导出的转义字符会导致"N为空值,这也不起作用:

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

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

6 个答案:

答案 0 :(得分:5)

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

从MySQL导出数据

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

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

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

导入大查询

这样您就可以使用以下内容将其导入大查询  参数:

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(<column>, '\t', ' '),它会从制表符转换为空格。

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

  3. 我希望这适合你。

答案 1 :(得分:1)

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

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

有了这个,你应该能够使用--null_marker="\N"导入数据。你可以尝试一下,让我知道它是否对你不起作用?

答案 2 :(得分:1)

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

但是在封闭器中,我要么使用默认\转义符转义了双引号问题,要么出现了带有“转义符”的空值问题,它变成了“ 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 + V Ctrl + A 创建它(更多信息{{3 }})。实际上只是一个字符。
  • 我们无法使用网络界面来创建表格,因为我们无法将控制字符定义为分隔符。

答案 3 :(得分:0)

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

使用mysql2csv,您可以运行任意查询,输出流程利用FasterCSV,这将为您提供比库存mysql更多的选项。

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

您可以尝试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