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 的情况下执行相同的操作。我保留 print
s 以检查它们不是缓慢的原因:
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 不提供自动设置这些选项的方法,因为使用这些选项数据库文件可能会因突然断电而损坏。
我使用 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 的情况下执行相同的操作。我保留 print
s 以检查它们不是缓慢的原因:
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 不提供自动设置这些选项的方法,因为使用这些选项数据库文件可能会因突然断电而损坏。