【发布时间】:2019-08-21 09:56:11
【问题描述】:
我正在制作一个程序来管理组件列表,我正在添加的功能之一是能够将文件添加为附件(使用 blob)。在我的测试中,我添加了一个大约 60MB 的文件,我注意到该行的 BOOL 字段的 SQlite UPDATE 比其他(大约 130k)慢得多。
做一些测试我注意到数据库文件大小是更新后的两倍,并且 HDD LED 在更新时亮起,所以看起来 sqlite 正在用新数据复制整行然后删除旧数据,而只是更新字段。
为了测试pourposes,我创建了这个简单的测试脚本:
# -*- coding: utf-8 -*-
import sqlite3
import os
from datetime import datetime
# Connect to database
conn = sqlite3.connect(
"test.sqlite3"
)
# Create table
with conn:
conn.execute(
"""CREATE TABLE IF NOT EXISTS Files (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
state BOOLEAN DEFAULT 0,
Filedata BLOB NOT NULL
);
"""
)
print("{}: Adding 60MB file to database".format(datetime.now()))
try:
with open("60MB.pdf", 'rb') as fIn:
_blob = fIn.read()
with conn:
conn.execute("INSERT INTO Files VALUES (?, ?, ?);", (None, False, sqlite3.Binary(_blob)))
print("{}: Finished".format(datetime.now()))
except Exception as e:
print("Error: {}".format(e))
print("{}: Adding 130k file to database".format(datetime.now()))
try:
with open("130k.pdf", 'rb') as fIn:
_blob = fIn.read()
with conn:
conn.execute("INSERT INTO Files VALUES (?, ?, ?);", (None, False, sqlite3.Binary(_blob)))
print("{}: Finished".format(datetime.now()))
except Exception as e:
print("Error: {}".format(e))
print("{}: Updating the state column of 60MB file".format(datetime.now()))
try:
with conn:
conn.execute("UPDATE Files SET state = 1 WHERE ID = 1;")
#conn.execute("UPDATE Files SET state = 0;")
print("{}: Finished".format(datetime.now()))
except Exception as e:
print("Error: {}".format(e))
print("{}: Same with 130k file".format(datetime.now()))
try:
with conn:
conn.execute("UPDATE Files SET state = 1 WHERE ID = 2;")
#conn.execute("UPDATE Files SET state = 0;")
print("{}: Finished".format(datetime.now()))
except Exception as e:
print("Error: {}".format(e))
conn.close()
#os.remove("test.sqlite3")
更新 130k 行大约需要 0.01s,而 60MB 行大约需要 0.5s(类似于 INSERT 时间)。
我认为我理解这个问题(每次更新都会复制整个数据),所以我的想法是创建一个只有 ID 和 BLOB 的单独表,并使用外键链接这两个表,但是在此之前,我想知道我是否做错了什么以及有更好的方法。
有人知道存储大 blob 数据的更好方法吗?
谢谢,问候。
【问题讨论】:
-
大 blob 可能应该存储为单独的文件,数据库只保存文件的路径。
标签: python-3.x sqlite