使用 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 并让守护程序加载它直接地。它的速度要快得多,并且可以进行许多优化。然后您可以使用分摊加载,如果您有多个文件要加载,您可以在文件列表中一起引用它们。

不过这个话题有点长。如果您有任何具体问题,请告诉我。