重复键值违反唯一约束 - 当试图从dask数据框架创建sql表时,postgres出现错误

12 人关注

Following on from this 问题,当我试图从一个有多个分区的dask.dataframe中创建一个postgresql表时,我得到了以下错误。

IntegrityError: (psycopg2.IntegrityError) duplicate key value violates unique constraint "pg_type_typname_nsp_index"
DETAIL:  Key (typname, typnamespace)=(test1, 2200) already exists.
 [SQL: '\nCREATE TABLE test1 (\n\t"A" BIGINT, \n\t"B" BIGINT, \n\t"C" BIGINT, \n\t"D" BIGINT, \n\t"E" BIGINT, \n\t"F" BIGINT, \n\t"G" BIGINT, \n\t"H" BIGINT, \n\t"I" BIGINT, \n\t"J" BIGINT, \n\tidx BIGINT\n)\n\n']

你可以用下面的代码重新创建这个错误。

import numpy as np
import dask.dataframe as dd
import dask
import pandas as pd
import sqlalchemy_utils as sqla_utils
import sqlalchemy as sqla
DATABASE_CONFIG = {
    'driver': '',
    'host': '',
    'user': '',
    'password': '',
    'port': 5432,
DBNAME = 'dask'
url = '{driver}://{user}:{password}@{host}:{port}/'.format(
        **DATABASE_CONFIG)
db_url = url.rstrip('/') + '/' + DBNAME
# create db if non-existent
if not sqla_utils.database_exists(db_url):
    print('Creating database \'{}\''.format(DBNAME))
    sqla_utils.create_database(db_url)
conn = sqla.create_engine(db_url)
# create pandas df with random numbers
df = pd.DataFrame(np.random.randint(0,40,size=(100, 10)), columns=list('ABCDEFGHIJ'))
# add index so that it can be used as primary key later on
df['idx'] = df.index
# create dask df
ddf = dd.from_pandas(df, npartitions=4)
# Write to psql
dto_sql = dask.delayed(pd.DataFrame.to_sql)
out = [dto_sql(d, 'test', db_url, if_exists='append', index=False, index_label='idx')
       for d in ddf.to_delayed()]
dask.compute(*out)

如果npartitions设置为1,代码就不会产生错误。 所以我猜测这与postgres不能处理向同一个sql表写入的并行请求有关......?我怎样才能解决这个问题呢?

1 个评论
我在数据框架并行运行过程中遇到了同样的问题,我按照@genchev的建议使用了锁,但对于并行化,你需要按照这个答案的步骤来做 stackoverflow.com/questions/25557686/...
python
postgresql
pandas
dask
pandas-to-sql
Ludo
Ludo
发布于 2019-01-25
3 个回答
Glori P.
Glori P.
发布于 2019-04-02
已采纳
0 人赞同

我在读 this . 似乎这个错误在你以并行处理方式创建/更新同一个表时出现。我知道这取决于 this (正如在谷歌小组讨论中所解释的那样)。

所以我认为这取决于 PostgreSQL 本身,而不是来自连接驱动或用于多进程的模块。

好吧,事实上,我发现解决这个问题的唯一方法是创建足够大的块,使回写过程比计算本身更慢。 有了更大的块,这个错误就不会上升。

不是完全相同的情况,但是当我(错误地)有两个连接到PSQL,在两个终端中运行一个相同的 CREATE TABLE 种子脚本时,我得到了这个错误。 杀死一个或两个终端,只重启一个终端,就解决了这个问题。
在部署到heroku时,也出现了同样的错误。我等了几分钟,然后打开应用程序。错误已经消失了。我的猜测是:当heroku还在创建表格时,我试图使用该应用程序。
Sergey Nakonechny
Sergey Nakonechny
发布于 2019-04-02
0 人赞同

在PostgreSQL中,这有助于我。

set enable_parallel_hash=off;

在你可以打开它之后

set enable_parallel_hash=on;
    
genchev
genchev
发布于 2019-04-02
0 人赞同

我在Heroku的PostgreSQL上的ponyORM也遇到了同样的错误。 我通过锁定线程来解决这个问题,直到它执行DB操作。在我的例子中。