Python 3.x Python数据保存性能

Python 3.x Python数据保存性能,python-3.x,postgresql,redis,sqlalchemy,Python 3.x,Postgresql,Redis,Sqlalchemy,我在数据方面遇到了一些瓶颈,敬请高层指教 我有一个API,在那里我接收的财务数据看起来像这样,我的目标是尽快将这些数据直接写入数据库 投入: Python 3.8 Pastgresql12 Redis队列(Linux) 炼金术 如上所示,传入的数据结构位于一个字典{symbol:{datetime:(price1,price2)}。所有数据都以Stringdatatype格式提供 API正在传输29个符号,因此我可以在一秒钟内接收不同符号的30到60+个值 它现在的工作原理: 我在字典里得到

我在数据方面遇到了一些瓶颈,敬请高层指教

我有一个API,在那里我接收的财务数据看起来像这样,我的目标是尽快将这些数据直接写入数据库

投入:

  • Python 3.8
  • Pastgresql12
  • Redis队列(Linux)
  • 炼金术
如上所示,传入的数据结构位于一个字典
{symbol:{datetime:(price1,price2)}
。所有数据都以
String
datatype格式提供

API正在传输29个符号,因此我可以在一秒钟内接收不同符号的30到60+个值

它现在的工作原理:

  • 我在字典里得到了新的价值
  • 每个符号的所有新值在我看来都存储在一个变量dict-
    data_dict
  • 接下来,我将按符号键和最后一个值询问这些字典,并将这些数据发送到Redis队列-
    data\u dict[symbol][last\u value]。排队(save\u record,args=(datetime,price1,price2))
    。在这一点上,一切都很好,很快
  • 对于Redis worker,有保存记录功能:
  • "

    当我执行函数的最后一行时,将这些行写入数据库需要0.5到1秒的时间:

    12:49:23默认值:DT.save_记录('2020-00-00 00:00:01.414538',1.33085,1.33107,'USDCAD',postgresql cred')(作业id_1)

    12:49:24默认值:作业正常(作业id\u 1)

    12:49:24默认值:DT.save_记录('2020-00-00 00:00:01.422541',1.56182,1.56213,'EURCAD','postgresql cred')(作业id_2)

    12:49:25默认值:作业正常(作业id\u 2)

    将每一行直接插入数据库的排队作业是一个瓶颈,因为我在1秒内只能插入1-2个值,并且我可以在1秒内接收60多个值。如果我运行此保存,它将开始创建巨大的队列(在API侦听1小时后,队列中的最大记录数为17.000条),并且不会停止rhose大小

    我目前只使用1个队列和17个工人。这使我的电脑CPU运行在100%

    所以问题是如何优化这个过程,而不是创建巨大的队列。也许可以尝试将一些序列保存在JSON中,然后插入数据库,或者将传入的数据存储在单独的变量中

    对不起,如果有什么疑问,问吧,我会回答的

    --UPD-- 下面是我对一些实验的小评论:

  • 引擎
    移出功能
  • 由于我的架构,API应用程序位于Windows 10上,Redis队列位于Linux上。出现了一个问题,即将
    meta
    engine
    移出功能,它返回TypeError(不取决于操作系统),以及一些有关它的信息

  • 在批处理中插入多行: 这种方法似乎是最简单、最简单的——事实就是如此!基本上,我刚刚创建了dictionary:
    data\u dict={'data\u pack':[]}
    ,开始存储传入的值。然后我询问每个符号是否有超过20个值已写入就绪-我将这些分支发送到Redis队列,在数据库中写入需要1.5秒。然后我从
    数据目录中删除记录,并继续处理。因此,感谢Mike Organek的良好建议

  • 这些方法对于我的目标来说已经足够了,同时我可以说这一堆技术可以为您提供非常好的灵活性!

    每次您调用
    保存记录
    时,您都会重新创建
    引擎
    和(反射)
    meta
    对象,这两个对象都是昂贵的操作。按原样运行示例代码使我的吞吐量达到

    在4.9秒内插入20行

    只需将
    engine=
    meta=
    语句移到
    save\u record
    函数之外(从而只调用它们一次),就可以提高吞吐量

    在0.3秒内插入20行


    附加说明:您似乎将每个符号的值存储在一个单独的表中,即名为
    GBPUSD
    的表中的“GBPUSD”数据,名为
    EURCAD
    的表中的“EURCAD”数据,等等。这是一个“红旗”“建议数据库设计不好。您应该将所有数据存储在一个表中,表中的符号列为列。

    是否需要使用SQLAlchemy?如果是这样,我帮不了你。调用
    engine.connect()
    是否为要插入的每一行创建到数据库的新连接?否,我不需要使用SQLAlchemy,是的,每次创建新连接(将每一行插入到数据库)时都会创建新连接),这种方法首先起作用,所以没有什么重要的用途,我可以自由选择任何模块或bibl。首先要看的是插入的每一行的连接。建立连接有很高的开销,您可以改变这一点并继续使用SQLAlchemy。如果这还不够快,那么我不确定是否可以使用SQLAlchemy完成以下步骤。第二个位置是一次只执行一行插入。您应该批量插入多行。第三个地方是使用预处理语句来消除查询解析开销。如果您对此有任何疑问,请发表评论。谢谢,在每个步骤中都与您保持一致,我们将逐一尝试,然后查看,无论如何,我们都会回复结果@MikeOrganek增加了UPD部分,谢谢!非常好的预约,谢谢,在函数外部调用
    引擎
    时出现一些问题,但我将搜索方法。您能提供您的方法吗?您是如何在函数外部调用的,因为当我尝试这样做时,我得到了
    TypeError:cannotpickle'\u thread.\u local'对象
    @Artem-我实际上只是将
    引擎=
    元=
    语句移动到
    保存\r上面
    
    def save_record(Datetime, price1, price2, Instr, adf):
    
    # Parameters
    #----------
    #    Datetime    : 'string'   : Datetime value
    #    price1      : 'string'   : Bid Value
    #    price2      : 'string'   : Ask Value
    #    Instr       : 'string'   : symbol to save
    #    adf         : 'string'   : Cred to DataBase engine
    #-------
    #    result      :            : Execute save command to database
    
    engine = create_engine(adf)
    meta = MetaData(bind=engine,reflect=True)
    table_obj = Table(Instr,meta)
    
    insert_state = table_obj.insert().values(Datetime=Datetime,price1=price1,price2=price2)
    
    with engine.connect() as conn:
        conn.execute(insert_state)