我有一个有一百万行的数据库,我想获取所有行并对它们进行一些操作,然后将它们插入另一个表(newTable)。
我发现我需要使用服务器端游标,因为我无法将所有数据提取到内存中。而且我还发现我需要使用两个连接,所以当我提交时,我不会松开我所做的光标。
但现在我的问题是,它不会像日志中显示的那样将所有记录放入 newTable 中。在控制台日志中,我看到它尝试将第 500,000 条记录插入数据库
560530 inserting 20551581 and 2176511
但是当我对创建的表进行计数时(当它在做的时候)它在新表中只显示了大约 10,000 行。
select count(*) from newTable;
count
-------
10236
当程序完成时,我在新表中只有大约 11000 条记录,而在记录中它显示它试图插入至少 200 万行。我的代码有什么问题?
def fillMyTable(self):
try:
self.con=psycopg2.connect(database='XXXX',user='XXXX',password='XXXX',host='localhost')
cur=self.con.cursor(name="mycursor")
cur.arraysize=1000
cur.itersize=2000
self.con2=psycopg2.connect(database='XXXX',user='XXXX',password='XXXX',host='localhost')
cur2=self.con2.cursor()
q="SELECT id,oldgroups from oldTable;"
cur.execute(q)
i=0
while True:
batch= cur.fetchmany()
if not batch:
break
for row in batch:
userid=row[0]
groupids=self.doSomethingOnGroups(row[1])
for groupid in groupids:
# insert only if it does NOT exist
i+=1
print (str(i)+" inserting "+str(userid)+" and "+str(groupid))
q2="INSERT INTO newTable (userid, groupid) SELECT %s, %s WHERE NOT EXISTS ( SELECT %s FROM newTable WHERE groupid = %s);"%(userid,groupid,userid,groupid)
cur2.execute(q2)
self.con2.commit()
except psycopg2.DatabaseError, e:
self.writeLog(e)
finally:
cur.close()
self.con2.commit()
self.con.close()
self.con2.close()
更新:我还注意到它使用了我的大量内存,服务器端光标不应该这样做吗?
Cpu(s): 15.2%us, 6.4%sy, 0.0%ni, 56.5%id, 2.8%wa, 0.0%hi, 0.2%si, 18.9%st 内存: 1695220k 总计, 1680496k 已使用, 14724k 空闲, 3084k 缓冲区交换:总共 0k,使用 0k,免费 0k,缓存 1395020k