我试图使用python脚本将大约5000万个数据插入到postgresql中。我的文件包含50万条记录。我对PostgreSQL和Python也是全新的。我尝试下面的代码插入python中,我在这里面临一个挑战。我的test.txt包含一个键值对,如下所示。
如果同一个键在文本文件中出现两次,我想用现有值附加值。我不知道如何在python中做到这一点。你能帮一些人帮忙吗?
myfile.txt的
key1 item1,product1,model1,price1|
key2 item2,product2,model2,price2|
key3 item3,product3,model3,price3|
key4 item4,product4,model4,price4|
key2 item22,product22,model22,price22|
在这种情况下,key2有两条记录 - 插入数据库时我会用第一个值附加第二个值。
表格列:
key value
key1 item1,product1,model1,price1|
key2 item2,product2,model2,price2|item22,product22,model22,price22|
key3 item3,product3,model3,price3|
key4 item4,product4,model4,price4|
insert.py
import psycopg2
def insertToDB(fileName):
conn = psycopg2.connect("dbname='mydb' user='testuser' host='localhost'")
with open(fileName) as f:
for line in f:
k,v = line.split(' ',1)
cursor = conn.cursor()
query = "INSERT INTO mytable (key,value) VALUES (%s,%s);"
data = (key,value)
cursor.execute(query,data)
conn.commit()
insertfile('myfile.txt')
我有大约5000万个数据,大多数密钥可能会重复使用不同的记录,如何处理以及我们如何有效地写入数据库?
如果有人可以建议即兴创作,那将会非常有用吗?
谢谢!
答案 0 :(得分:2)
最简单的方法是使用SQL insert语句的ON CONFLICT
子句。这会将您的简单插入更改为“upsert”(插入或更新)。
ON CONFLICT
需要PostgreSQL 9.5或更高版本,并且使用如下:
query = """INSERT INTO mytable (key,value)
VALUES (%s,%s)
ON CONFLICT (key)
DO UPDATE SET value = CONCAT(users.value, %s);"""
cursor.execute(query, (key, value, value))
另一种选择是在通过重构数据将结果发送到数据库之前连接结果。在这里,我按字典中的键收集所有行,然后在插入时我只是将所有值加在一起。
这样,每个键只有一个插入。
以下是一些解释此问题的代码:
from collections import defaultdict
import psycopg2
def get_records(filename):
records = defaultdict(list)
with open(filename) as f:
for line in f:
if line.strip():
key, value = line.split(' ',1)
records[key].append(value)
return records
def insert_records(records, conn):
q = "INSERT INTO mytable (key, value) VALUES (%s, %s);"
cursor = conn.cursor()
for key, data in records.items():
cursor.execute(q, (key, ''.join(data)))
conn.commit()
conn = psycopg2.connect("dbname='mydb' user='testuser' host='localhost'")
insert_records(get_records('myfile.txt'), conn)
如果您有大量记录,可能是因为您一次加载整个文件而耗尽内存。
相反,您可以实现一种更简单的算法来跟踪读取的密钥。
def insert_records(filename, conn):
seen = set()
cursor = conn.cursor()
qi = "INSERT INTO mytable (key, value) VALUES (%s, %s);"
qu = "UPDATE mytable SET value = CONCAT(value, %s) WHERE key = %s;"
with open(filename) as f:
for line in f:
if line.strip():
key, value = line.split(' ', 1)
if key not in seen:
# first time we see this key, do an insert
seen.add(key)
cursor.execute(qi, (key, value))
else:
# key has been processed at least once, do an update
cursor.execute(qu, (value, key))
conn.commit()
conn = psycopg2.connect("dbname='mydb' user='testuser' host='localhost'")
insert_records(filename, conn)