postgres python服务器端游标不会插入所有数据

时间:2013-07-30 15:27:10

标签: python postgresql cursor psycopg2

我有一个包含一百万行的数据库,我想获取所有行并对它们进行一些操作,然后将它们插入另一个表(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()

更新:我还注意到它使用了很多我的RAM,不是服务器端游标不应该这样做吗?

  

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 Mem:1695220k总计,1680496k使用,14724k免费,3084k缓冲交换:总共0k,0k使用,0k免费,   1395020k缓存

1 个答案:

答案 0 :(得分:1)

如果oldgroups列的格式为1,3,6,7,则可以使用:

insert into newTable (userid, groupid)
select id, groupid
from (
    select
        id,
        regexp_split_to_table(olgroups, ',') as groupid
    from oldTable
) o
where
    not exists (
        select 1
        from newTable
        where groupid = o.groupid
    )
    and groupid < 10000000

但我怀疑你想要检查是否存在groupid和id:

insert into newTable (userid, groupid)
select id, groupid
from (
    select
        id,
        regexp_split_to_table(olgroups, ',') as groupid
    from oldTable
) o
where
    not exists (
        select 1
        from newTable
        where groupid = o.groupid and id = o.id
    )
    and groupid < 10000000

regexp_split_to_table函数将“爆炸”与id列交叉连接的行中的oldgroups列。