Python函数进行了太多的数据库更新

Python函数进行了太多的数据库更新,python,postgresql,Python,Postgresql,这有点让人困惑 我有一个数据库表,它有一组作为列的统计数据,一组非常相似的平均值 设置一个函数来迭代我的数据集很多次,并更新数据库中的行很多次,这真的很容易 但是它的速度太慢了,而且一个大而长的脚本,只需要一次更新一组,写起来会花很多时间,维护起来也会很痛苦 我想知道是否有一种方法既可以是面向对象的,又可以不做那么多冗余的搜索/数字运算 我想知道是否有更简单的方法。。。SSIS会让我只提取一次数据,最后将其合并,然后将其扔回数据库。但我不确定我会如何用Python做到这一点 因此,我在pytho

这有点让人困惑

我有一个数据库表,它有一组作为列的统计数据,一组非常相似的平均值

设置一个函数来迭代我的数据集很多次,并更新数据库中的行很多次,这真的很容易

但是它的速度太慢了,而且一个大而长的脚本,只需要一次更新一组,写起来会花很多时间,维护起来也会很痛苦

我想知道是否有一种方法既可以是面向对象的,又可以不做那么多冗余的搜索/数字运算

我想知道是否有更简单的方法。。。SSIS会让我只提取一次数据,最后将其合并,然后将其扔回数据库。但我不确定我会如何用Python做到这一点

因此,我在python中定义了一个函数,该函数平均运行n天:

def moving_average(conn, cur, dates, days, stockid, col_name):
#    print days
    if (len(dates) < days):
        print "WARNING: Cannot do a " + str(days) + " day moving average for stock id " + str(stock_id) + "!  Not enough data!"
    else:
        for x in range (0, len(dates) - int(days) - 1):
            row_id = dates[x][0]
            numerator = 0
            for i in range (0, days - 1):
                numerator = numerator + dates[x][3]
                moving_average_for_period = round(numerator / days, 2)
                sql = "UPDATE historical_prices SET " + col_name + " = " + str(moving_average_for_period) + " WHERE id = " + str(row_id) + ";"
                cur.execute(sql) 
        conn.commit()
看到我的问题了吗?我做我的I/O 6x

提前感谢您的帮助

干杯


Dan

虽然纯SQL通常比Python或Java一次更新一次要快,但等在一个大表上执行更新可能会很快变得指数级慢,这取决于表的大小,即使是更新的行数相对较少

如果您选择纯SQL路线,我的意思是从Python执行一个影响大量行的更新—在本例中,我绝对推荐这种方法—我建议使用LIMIT和OFFSET对其进行分块,这样每次更新都会小得多。博士后通常能够更好地处理这一问题。我曾经遇到过这样的情况:一个更新在5个多小时后无法在一块中完成,而当我通过Python以5000块的形式完成时,它只需要30分钟就完成了


当然,如果您的表足够小,您可能不会遇到这个问题,但这是需要记住的。

速度慢不是因为您这样做了六次,而是因为您在每个移动平均值呼叫中进行了^2次更新。有两种方法可以做到这一点:1。将日期加载到数据库中,然后编写单个查询来更新数据;2.将整个表加载到内存中,对其进行操作,然后一次性将其保存回去。您所采用的方法取决于日期的相对大小和历史价格表。如果您决定使用SQL进行此操作,下面是一篇关于如何在PostgreSQL中进行移动平均的好文章:@univerio,谢谢您的评论!:我没有在SQL中这样做的原因是,在我所在的上一家商店,我们的表几乎有数百万行,如果我进行SQL更新,它可能会持续数小时,但如果我使用SSIS,则需要5分钟——从SELECT中获取数据,在内存中更新数据,并将其发送回数据库我猜SSIS没有使用更新查询来完成这项工作?我本以为python会同样快或更快,但似乎我需要用一种不同的范式来思考
  # now do the moving averages
    moving_average(conn,cur,dates,5,stock_id,'five_day_ma')
    moving_average(conn,cur,dates,10,stock_id,'ten_day_ma')
    moving_average(conn,cur,dates,15,stock_id,'fifteen_day_ma')
    moving_average(conn,cur,dates,30,stock_id,'thirty_day_ma')
    moving_average(conn,cur,dates,60,stock_id,'sixty_day_ma')
    moving_average(conn,cur,dates,120,stock_id,'onetwenty_day_ma')