2013-12-18 67 views
0

当我处理100,000条记录或附近时,得到了运行速度非常快的脚本(处理30,000条记录的时间约为20秒)。这些脚本从postgresql数据库获取记录,处理它们,然后在数据库中标记这些记录已被处理。如何在postgresql中加速批量更新

问题是我现在已经将脚本指向一个拥有5000万条记录的数据库,现在有10000条记录需要大约160秒!这非常缓慢。

有什么我可以做,以加快我的更新?

我Python和SQLAlchemy的核心代码是:

def process_records(no_of_records, data) 
    for x in range(no_of_records): 
     my_data = data[x] 
      '''process the data, when done, mark as is_processed''' 
     dict = {} 
     dict['b_id'] = pid 
     dict['is_processed'] = is_processed 
     is_processed_list.append(dict) 

    CONN = Engine.connect() 
    trans = CONN.begin() 
    stmt = mytable.update().where(mytable.c.id == bindparam('b_id')).\ 
    values(is_processed=bindparam('is_processed')) 
    CONN.execute(stmt, is_processed_list) 
    trans.commit() 

编辑

我异型我的代码,我意识到这个问题是不是与这条巨蟒循环,甚至与批量插入。问题where I was loosing 80+ seconds首先选择要处理的数据。一旦我明白了这一点,那么@马丁的建议,我包括一个索引和它的速度!

+0

(在clippy语音中):看起来你正在处理它自己的事务中的每一行。您是否考虑过一次处理一笔交易中的多行? –

+0

@ScottMarlowe实际上是在做批量更新。如果仔细检查语法,update语句会出现在for循环之后,即update语句运行'is_processed_list',每个更新大约有10,000条记录。 for循环非常快。以微秒运行。只有批量更新才能让上帝永远知道。 – lukik

+0

啊,好的。是的,从你的代码来看,这对我来说并不明显。很高兴你找到了你真正的问题。 –

回答

2

你应该检查查询规划器告诉你什么。使用“EXPLAIN”前缀SQL查询以获取有关Postgresql试图执行的操作的详细信息。首先,试着选择应该更新的行,看看会发生什么。

如果它的选择部分很慢(阅读),则可以通过在此条件下使用索引来紧固(mytable.c.id == b_id)。请注意,在Postgresql中,FOREIGN KEY不会为您的表建立索引。

见这里了解详细信息说明:http://www.postgresql.org/docs/current/static/sql-explain.html

如果是写入的部分即是慢,你可能需要调整的PostgreSQL配置。

+0

你明白了。我假设外键是默认索引的。所以我在该列上创建了一个索引,而select语句现在是Micro Seconds。甚至不觉得它的5000万条记录!尽管如此,我有一台16GB的机器运行8核心的Ubuntu服务器。我编辑过的配置包括kernel.shmmax = 4294967296,kernel.shmall = 1073741824并设置shared_buffers = 3500MB。更多的建议欢迎 – lukik