我有一个简单的服务应用程序:python、tornado 网络服务器、sqlite 数据库。数据库已加密。
问题是处理非常简单的 http 请求需要大约 300 毫秒。
从日志中我可以看到,大部分时间都花在了第一个 sql 请求的处理上,无论这个第一个请求多么简单。后续的 sql 请求处理得更快。但是随后服务器开始处理下一个 http 请求,并且第一个 sql 请求再次非常慢。
如果我关闭数据库加密,问题就消失了:sql 请求的处理时间不依赖于请求是否是第一个请求,我的服务器响应时间减少了 10 到 15 倍。
我不太明白这是怎么回事。看起来 sqlalchemy 每次启动新 session 时都会读取和解密数据库文件。有什么办法可以解决这个问题?
最佳答案
由于 pysqlite 或 sqlite3
模块如何工作 SQLAlchemy defaults to using a NullPool
with file-based databases .这解释了为什么每个请求都会对您的数据库进行解密:NullPool
在连接关闭时丢弃它们。这样做的原因是 pysqlite 的默认行为是不允许在多个线程中使用连接,并且在不加密的情况下创建新连接非常快。
Pysqlite 确实有一个未记录的标志 check_same_thread
可用于禁用检查,但应谨慎处理线程之间的共享连接,并且 SQLAlchemy 文档顺便提到 NullPool
与 SQLite 的文件锁定配合使用效果很好。
根据您的 Web 服务器,您可以使用 SingletonThreadPool
,这意味着线程中的所有连接都是相同的连接:
engine = create_engine('sqlite:///my.db',
poolclass=SingletonThreadPool)
如果您喜欢冒险并且您的 Web 服务器在使用时不在线程之间共享连接/ session (例如使用范围 session ),那么您可以尝试使用与 check_same_thread=False配对的不同池化策略
:
engine = create_engine('sqlite:///my.db',
poolclass=QueuePool,
connect_args={'check_same_thread':False})
关于 python ,sqlalchemy : how to improve performance of encrypted sqlite database?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52976097/