使用 Uber 的 vertica-python 包使用 Python 批量插入 Vertica
Bulk insert into Vertica using Python using Uber's vertica-python package
第 1 题,共 2 题
我正在尝试使用 Python 将数据从 CSV 文件导入 Vertica,使用 Uber 的 vertica-python 包。问题是只有空白的数据元素被作为 NULL 加载到 Vertica 中;我只想将空数据元素作为 NULL 加载,而不是将非空空白数据元素作为空格加载。
例如,CSV 文件的以下两行都作为 ('1','abc',NULL,NULL) 加载到数据库中,而我希望将第二行加载为 ( '1','abc','',NULL).
1,abc,,^M
1,abc, ,^M
代码如下:
# import vertica-python package by Uber
# source: https://github.com/uber/vertica-python
import vertica_python
# write CSV file
filename = 'temp.csv'
data = <list of lists, e.g. [[1,'abc',None,'def'],[2,'b','c','d']]>
with open(filename, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f, escapechar='\', doublequote=False)
writer.writerows(data)
# define query
q = "copy <table_name> (<column_names>) from stdin "\
"delimiter ',' "\
"enclosed by '\"' "\
"record terminator E'\r' "
# copy data
conn = vertica_python.connect( host=<host>,
port=<port>,
user=<user>,
password=<password>,
database=<database>,
charset='utf8' )
cur = conn.cursor()
with open(filename, 'rb') as f:
cur.copy(q, f)
conn.close()
第 2 题,共 2 题
使用这种将数据加载到 Vertica 的方法是否还有其他问题(例如字符编码)需要注意?代码中还有其他错误吗?我不是 100% 相信它会在所有平台上运行(目前 运行ning 在 Linux 上;例如,在其他平台上可能存在记录终止符问题)。任何使此代码更健壮的建议将不胜感激。
此外,是否有其他方法可以将数据从 Python 批量插入 Vertica,例如直接从 Python 加载对象而不是先将它们写入 CSV 文件,而不牺牲速度?数据量很大,按原样插入作业需要几个小时 运行.
提前感谢您提供的任何帮助!
您的复制语句应该按照您希望的方式执行空格。我使用非常相似的 COPY
对其进行了测试。
编辑:我错过了你真正想问的副本,我将保留这部分,因为它可能对某些人仍然有用:
要修复空白,您可以更改复制语句:
copy <table_name> (FIELD1, FIELD2, MYFIELD3 AS FILLER VARCHAR(50), FIELD4, FIELD3 AS NVL(MYFIELD3,'') ) from stdin
通过使用填充符,它会将其解析为变量之类的东西,然后您可以在稍后的副本中使用 AS
将其分配给实际的 table 字段。
至于任何陷阱......我经常做你在 Solaris 上做的事情。我注意到的唯一一件事是您正在设置记录终止符,不确定这是否真的是您需要根据环境做的事情。我从来不需要在 linux、windows 和 solaris 之间切换。
此外,请注意,这将 return 一个结果集,告诉您加载了多少行。做一个 fetchone()
并打印出来,你就会看到它。
我唯一可以推荐的另一件事可能是使用 reject tables 以防任何行被拒绝。
您提到这是一项庞大的工作。您可能需要通过将 'read_timeout': 7200,
添加到您的连接或更多来增加读取超时。我不确定 None 是否会禁用读取超时。
至于更快的方法...如果文件可以直接在 vertica 节点本身上访问,您可以直接在副本中引用该文件,而不是执行 copy from stdin
并让守护程序加载它直接地。它的速度要快得多,并且可以进行许多优化。然后您可以使用分摊加载,如果您有多个文件要加载,您可以在文件列表中一起引用它们。
不过这个话题有点长。如果您有任何具体问题,请告诉我。
第 1 题,共 2 题
我正在尝试使用 Python 将数据从 CSV 文件导入 Vertica,使用 Uber 的 vertica-python 包。问题是只有空白的数据元素被作为 NULL 加载到 Vertica 中;我只想将空数据元素作为 NULL 加载,而不是将非空空白数据元素作为空格加载。
例如,CSV 文件的以下两行都作为 ('1','abc',NULL,NULL) 加载到数据库中,而我希望将第二行加载为 ( '1','abc','',NULL).
1,abc,,^M
1,abc, ,^M
代码如下:
# import vertica-python package by Uber
# source: https://github.com/uber/vertica-python
import vertica_python
# write CSV file
filename = 'temp.csv'
data = <list of lists, e.g. [[1,'abc',None,'def'],[2,'b','c','d']]>
with open(filename, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f, escapechar='\', doublequote=False)
writer.writerows(data)
# define query
q = "copy <table_name> (<column_names>) from stdin "\
"delimiter ',' "\
"enclosed by '\"' "\
"record terminator E'\r' "
# copy data
conn = vertica_python.connect( host=<host>,
port=<port>,
user=<user>,
password=<password>,
database=<database>,
charset='utf8' )
cur = conn.cursor()
with open(filename, 'rb') as f:
cur.copy(q, f)
conn.close()
第 2 题,共 2 题
使用这种将数据加载到 Vertica 的方法是否还有其他问题(例如字符编码)需要注意?代码中还有其他错误吗?我不是 100% 相信它会在所有平台上运行(目前 运行ning 在 Linux 上;例如,在其他平台上可能存在记录终止符问题)。任何使此代码更健壮的建议将不胜感激。
此外,是否有其他方法可以将数据从 Python 批量插入 Vertica,例如直接从 Python 加载对象而不是先将它们写入 CSV 文件,而不牺牲速度?数据量很大,按原样插入作业需要几个小时 运行.
提前感谢您提供的任何帮助!
您的复制语句应该按照您希望的方式执行空格。我使用非常相似的 COPY
对其进行了测试。
编辑:我错过了你真正想问的副本,我将保留这部分,因为它可能对某些人仍然有用:
要修复空白,您可以更改复制语句:
copy <table_name> (FIELD1, FIELD2, MYFIELD3 AS FILLER VARCHAR(50), FIELD4, FIELD3 AS NVL(MYFIELD3,'') ) from stdin
通过使用填充符,它会将其解析为变量之类的东西,然后您可以在稍后的副本中使用 AS
将其分配给实际的 table 字段。
至于任何陷阱......我经常做你在 Solaris 上做的事情。我注意到的唯一一件事是您正在设置记录终止符,不确定这是否真的是您需要根据环境做的事情。我从来不需要在 linux、windows 和 solaris 之间切换。
此外,请注意,这将 return 一个结果集,告诉您加载了多少行。做一个 fetchone()
并打印出来,你就会看到它。
我唯一可以推荐的另一件事可能是使用 reject tables 以防任何行被拒绝。
您提到这是一项庞大的工作。您可能需要通过将 'read_timeout': 7200,
添加到您的连接或更多来增加读取超时。我不确定 None 是否会禁用读取超时。
至于更快的方法...如果文件可以直接在 vertica 节点本身上访问,您可以直接在副本中引用该文件,而不是执行 copy from stdin
并让守护程序加载它直接地。它的速度要快得多,并且可以进行许多优化。然后您可以使用分摊加载,如果您有多个文件要加载,您可以在文件列表中一起引用它们。
不过这个话题有点长。如果您有任何具体问题,请告诉我。