2

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

一些操作,例如插入,似乎非常慢。一次插入包含 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 查询字符串打印得很快,所以我猜这里的翻译不是问题,但是正如你所看到的,整个操作需要几秒钟。

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

4

1 回答 1

4

我认为问题是由慢速 SD 卡引起的。在COMMIT执行期间,SQLite 将数据刷新到卡中,并且此操作对于 SD 卡可能会很慢。SQLite 在 Raspberry PI 上运行缓慢是一个已知问题,尤其是在卡类低于 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 pragmaPRAGMA synchronous = OFFPRAGMA journal_mode = MEMORY. 目前 PonyORM 不提供自动设置这些选项的方法,因为使用这些选项,数据库文件可能会因突然断电而损坏。

于 2016-03-09T13:28:33.857 回答