我正在尝试使用python脚本将已从BigQuery导出的csv文件从Google Cloud Storage(GCS)迁移到PostgreSQL Google Cloud sql实例。
我希望使用Google API,但在the documentation中找到了它:
PostgreSQL实例不支持使用Cloud SQL Admin API导入CSV数据。
作为替代方案,我可以使用psycopg2
库并将csv文件的行流式传输到SQL实例中。我可以通过三种方式做到这一点
我担心的是,这些csv文件可能包含数百万行,因此对上述三个选项中的任何一个运行此过程对我来说都是一个坏主意。
我有什么选择? 本质上,我在BigQuery中有一些原始数据,在导出到GCS之前,我们会对其进行一些预处理,以准备导入PostgreSQL实例。 我需要将此预处理后的数据从BigQuery导出到PostgreSQL实例。
这不是此question的重复版本,因为我最好是寻找将数据从BigQuery导出到PostgreSQL实例的解决方案,无论它是通过GCS还是直接进行的。
答案 0 :(得分:2)
您可以按照@GrahamPolley的建议,使用Cloud Dataflow进行导入过程。的确,此解决方案涉及一些额外的工作(熟悉Dataflow,设置所有内容等)。即使进行了额外的工作,这仍将是适合您情况的首选解决方案。但是,还有其他解决方案可用,我将在下面说明其中一种。
要使用Dataflow设置迁移过程,本关于exporting BigQuery to Google Datastore的教程就是一个很好的例子
云数据流的替代解决方案
用于PostgreSQL的Cloud SQL不支持从.CSV
导入,但是它支持.SQL
文件。
指定uri的文件类型。
SQL:该文件包含SQL语句。
CSV:文件包含CSV数据。 PostgreSQL实例不支持使用Cloud SQL Admin API导入CSV数据。
一种直接的解决方案是使用某种工具(我不知道,但在线提供的工具很多)将.CSV
文件集转换为.SQL
,然后导入到PostgreSQL
如果您想以更“程序化”的方式实施此解决方案,我建议使用Cloud Functions,这是我尝试执行此操作的示例:
.CSV
。如果是这样,请使用csv-to-sql API(example of API here)将文件转换为.SQL
答案 1 :(得分:1)
我发现pyscopg2
模块具有copy_from(),它允许加载整个csv文件,而不是单独地流传输行。
使用此方法的缺点是,仍然需要从GCS下载csv文件并将其存储在本地。
以下是使用pyscopg2
'copy_from()'的详细信息。 (摘自here)
import psycopg2
conn = psycopg2.connect("host=localhost dbname=postgres user=postgres")
cur = conn.cursor()
with open('user_accounts.csv', 'r') as f:
# Notice that we don't need the `csv` module.
next(f) # Skip the header row.
cur.copy_from(f, 'users', sep=',')
conn.commit()
答案 2 :(得分:0)
您可以只使用一个类来使从互联网上提取的文本表现得像文件。我已经使用过几次了。
import io
import sys
class IteratorFile(io.TextIOBase):
""" given an iterator which yields strings,
return a file like object for reading those strings """
def __init__(self, obj):
elements = "{}|" * len(obj[0])
elements = (unicode(elements[:-1]).format(*x) for x in obj)
self._it = elements
self._f = io.cStringIO()
def read(self, length=sys.maxsize):
try:
while self._f.tell() < length:
self._f.write(next(self._it) + "\n")
except StopIteration as e:
# soak up StopIteration. this block is not necessary because
# of finally, but just to be explicit
pass
except Exception as e:
print("uncaught exception: {}".format(e))
finally:
self._f.seek(0)
data = self._f.read(length)
# save the remainder for next read
remainder = self._f.read()
self._f.seek(0)
self._f.truncate(0)
self._f.write(remainder)
return data
def readline(self):
return next(self._it)
答案 3 :(得分:0)
开始之前,请确保:
您要导入的数据库和表必须 您的Cloud SQL实例上已经存在。
CSV文件格式要求CSV文件每一行必须一行 的数据,并具有逗号分隔的字段。
然后,您可以按照后续步骤[GCLOUD] import data to a Cloud SQL instance using a CSV file出现在GCS存储桶中
gcloud sql instances describe [INSTANCE_NAME]
复制serviceAccountEmailAddress字段。
以编写者身份将服务帐户添加到存储桶ACL:
gsutil acl ch -u [SERVICE_ACCOUNT_ADDRESS]:W gs://[BUCKET_NAME]
gsutil acl ch -u [SERVICE_ACCOUNT_ADDRESS]:R gs://[BUCKET_NAME]/[IMPORT_FILE_NAME]
gcloud sql import csv [INSTANCE_NAME] gs://[BUCKET_NAME]/[FILE_NAME] \
--database=[DATABASE_NAME] --table=[TABLE_NAME]
gsutil acl ch -d [SERVICE_ACCOUNT_ADDRESS] gs://[BUCKET_NAME]