如果使用python

时间:2017-11-07 05:16:03

标签: python postgresql

我试图使用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万个数据,大多数密钥可能会重复使用不同的记录,如何处理以及我们如何有效地写入数据库?

如果有人可以建议即兴创作,那将会非常有用吗?

谢谢!

1 个答案:

答案 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)