Python 3.x Python数据保存性能
我在数据方面遇到了一些瓶颈,敬请高层指教 我有一个API,在那里我接收的财务数据看起来像这样,我的目标是尽快将这些数据直接写入数据库 投入: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+个值 它现在的工作原理: 我在字典里得到
- Python 3.8
- Pastgresql12
- Redis队列(Linux)
- 炼金术
{symbol:{datetime:(price1,price2)}
。所有数据都以String
datatype格式提供
API正在传输29个符号,因此我可以在一秒钟内接收不同符号的30到60+个值
它现在的工作原理:
data_dict
李>
data\u dict[symbol][last\u value]。排队(save\u record,args=(datetime,price1,price2))
。在这一点上,一切都很好,很快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--
下面是我对一些实验的小评论:
引擎
元
移出功能meta
和engine
移出功能,它返回TypeError(不取决于操作系统),以及一些有关它的信息
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)