【发布时间】:2021-11-23 08:25:03
【问题描述】:
最近几天我一直在开发一个非常简单的网页,我决定使用 SQLAlchemy 和 Flask 作为后端堆栈。
表 DDL:
create table if not exists testdb.table_datetime
(
id int auto_increment
primary key,
col1 varchar(50) null,
col2 varchar(50) null,
col3 varchar(50) null,
col4 varchar(50) null,
col5 varchar(50) null,
col6 varchar(50) null,
local_modified datetime null
)
collate=utf8mb4_bin;
我的 ORM 模型:
class DemoClass(Base):
__tablename__ = 'table_datetime'
local_modified = Column(DATETIME)
# __tablename__ = 'table_varchar'
# local_modified = Column(String)
id = Column(Integer, primary_key=True)
col1 = Column(String)
col2 = Column(String)
col3 = Column(String)
col4 = Column(String)
col5 = Column(String)
col6 = Column(String)
代码:
with Session() as session:
db_rows = session.query(DemoClass).all()
for item in data:
for db_row in db_rows:
if item['id'] == db_row.id:
db_row.col1 = item['col1']
db_row.col2 = item['col2']
db_row.col3 = item['col3']
db_row.col4 = item['col4']
db_row.col5 = item['col5']
db_row.col6 = item['col6']
# db_row.local_modified = item['local_modified'] # Very slow, 6-8s for 500 rows data
db_row.local_modified = datetime.strptime(item['local_modified'], '%Y-%m-%d %H:%M:%S') # Fast, <1s for 500 rows data
break
session.commit()
我发现将字符串 '2021-10-02 11:12:34' 分配给 ORM DATETIME 会比 datetime.strptime(2021-10-02 11:12:34', '%Y-%m-%d %H:%M:%S') 慢得多。
我的测试环境:
Flask==2.0.1
PyMySQL==1.0.2
MySQL==1.0.2
SQLAlchemy==1.4.25
Python 3.6.5 Windows
MySQL remote server, Server version 5.7.33-0ubuntu0.18.04.1
结果是,对于要更新的 500 行,分配一个日期时间字符串需要 6 到 10 秒,而先将日期时间字符串转换为 datetime 然后再分配需要不到 1 秒。
完整的测试代码和设置在这里:https://github.com/ajfg93/sqlalchemy-demo/tree/datetime_slow
我的问题是,性能下降是否合理(小于 1 秒 vs 6 到 10 秒)?
我猜如果我传递的是日期时间字符串而不是 datetime 对象,内部代码(SQLAlchemy 或 MySQL,我不知道谁会做这项工作)可能会尝试猜测字符串格式并得到一个datetime 认为正确的对象?但真的那么慢吗?还有其他原因吗?
如果我不测试代码,我可能永远不会知道它是db_row.local_modified = item['local_modified'] 减慢了整个处理流程。我的意思是,我更希望 SQLAlchemy 引发异常,告诉我数据类型不匹配,而不是导致这种巨大的性能下降。
【问题讨论】:
-
因为您已经完成了确定格式首先匹配有效日期的工作; SQLAlchemy 中的实际代码首先对字符串运行正则表达式,并指出这比 strptime 快,至少到 Python 2.6;可能只是
strptime现在更快的情况 - 但在添加功能时没有回来:github.com/sqlalchemy/sqlalchemy/blob/… - 它还指出 strptime 本身不支持微秒,但这也可能在较新的版本中发生了变化版本。 -
@MatsLindh 好吧,如果它那么慢,为什么不只是给我一个错误并强迫我决定我的代码中的格式。性能下降是不可接受的。
-
如前所述(并由评论指出); 在以前的平台上可能并不慢,而且这个问题可能只是最近才出现。我敢肯定,如果可能的话,有人会喜欢一个与今天的工作方式保持兼容性的补丁。附上一个profiler,看看两个不同版本的时间都花在了哪里;也许幕后还有其他事情发生。
-
@MatsLindh 我用 loal mysql 再次测试了它,所有响应时间
标签: python python-3.x sqlalchemy