PonyORM、SQLite 性能

PonyORM, SQLite performance

我使用 PonyORM 作为我的 SQLite 数据库的 ORM Python 3.5 on Raspberry PI 3(不是你能想象的最快的设备,但它不应该是那么不好)。

某些操作,例如插入,似乎非常慢。一次插入包含 3 个短字符串的实体可能需要 4 - 10 秒。

这是我的 datamodel.py 文件:

from pony.orm import *
from datetime import datetime

db = Database('sqlite', 'website.db', create_db = True)

class User(db.Entity):
    login = Required(str, unique=True)
    password = Required(str)
    actions = Set("Event")

class Event(db.Entity):
    description = Optional(str)
    date = Required(datetime)
    ip = Required(str)
    user = Optional(User)

db.generate_mapping(create_tables = True)

我还创建了一个非常简单的性能测试:

from datamodel import *
from datetime import *

sql_debug(True)
totalTime = datetime.now()
with db_session:
    constructTime = datetime.now()
    Event(date = datetime.now(),
          ip = '0.0.0.0',
          description = 'Sample event!')
    constructTime = datetime.now() - constructTime
totalTime = datetime.now() - totalTime
print(constructTime)
print(totalTime)

它的示例结果:

GET NEW CONNECTION
BEGIN IMMEDIATE TRANSACTION
INSERT INTO "Event" ("description", "date", "ip", "classtype") VALUES (?, ?, ?, ?)
['Sample event!', '2016-03-08 23:05:15.066742', '0.0.0.0', 'Event']

COMMIT
RELEASE CONNECTION
0:00:00.000479
0:00:04.808138

SQL 查询字符串的打印速度非常快,所以我想翻译不是这里的问题,但如您所见,整个操作需要几秒钟。

这可能是什么原因?有什么办法可以改善这个荒谬的长时间吗?

我认为是SD卡速度慢导致的。在 COMMIT 执行期间,SQLite 将数据刷新到卡中,对于 SD 卡,此操作可能会很慢。 SQLite 在 Raspberry PI 上运行缓慢是一个已知问题,尤其是当卡 class 低于 Class 10 时:https://spin.atomicobject.com/2013/11/14/sqlite-raspberry-pi/

您可以执行以下测试,以检查 PonyORM 是否是造成您的情况速度慢的原因:

1) 尝试使用内存数据库。为此,将带有数据库对象定义的行替换为以下行:

db = Database('sqlite', ':memory:', create_db=True)

2) 在不使用 PonyORM 的情况下执行相同的操作。我保留 prints 以检查它们不是缓慢的原因:

import sqlite3
from datetime import *

totalTime = datetime.now()
connection = sqlite3.connect('website.db', isolation_level=None)

sql = 'BEGIN IMMEDIATE TRANSACTION'
print(sql)
connection.execute(sql)

sql = 'INSERT INTO "Event" ("description", "date", "ip", "classtype") VALUES (?, ?, ?, ?)'
args = ('Sample event!', '2016-03-08 23:05:15.066742', '0.0.0.0', 'Event')
print(sql)
print(args)
connection.execute(sql, args)

sql = 'COMMIT'
print(sql)
connection.execute(sql)

totalTime = datetime.now() - totalTime
print(totalTime)

如果性能问题是SD卡引起的,第一个测试会立即执行,第二个测试和ORM一样慢。

也许可以通过使用 SQLite pragmas PRAGMA synchronous = OFF and PRAGMA journal_mode = MEMORY 获得更好的性能。目前 PonyORM 不提供自动设置这些选项的方法,因为使用这些选项数据库文件可能会因突然断电而损坏。