使用 SQLite 将 Blob 存储在单独的表中?
Storing Blobs in Seperate Tables with SQLite?
我正在使用这个 SQLite Plugin 作为移动应用程序来享受 'unlimited' 存储限制。基本上我有 base64 imagedata
并且需要将其存储在数据库中。
此外,我还有一些其他 tables 和一个 Masterdata,其中存储了主键以及一些附加信息,例如 albumName
.
使用外键建立关系
为了应对数据库的关系方面,我最初使用外键声明并创建了 table 如下(为简单起见,只显示了两个 table):
// Master Data
$cordovaSQLite.execute(db,
"CREATE TABLE IF NOT EXISTS \
Masterdata(\
id TEXT primary key, \
albumName TEXT, \
favorite INTEGER\
)"
)
// Images
$cordovaSQLite.execute(db,
"CREATE TABLE IF NOT EXISTS \
ImagesData(\
id TEXT, \
data BLOB, \
FOREIGN KEY(id) REFERENCES Masterdata(id)\
)"
)
然后,当我只想加载特定相册的图像时,我 运行 查询:
SELECT Masterdata.id, ImagesData.data FROM ImagesData, Masterdata WHERE Masterdata.album = (?) ["Some album name"]
这工作正常(一切正常加载),但我立即注意到它在处理大型数据集时变慢了。这是有道理的,因为 base64 字符串的存储空间很大。
将 Blob 存储在单独的表中
所以我读了这个 post, 如果您的数据包含 BLOB,建议考虑将每个 BLOB 存储在单独的 table 中。
我编码如下:
// tableName in the form of 'id'_imagesData
// 'id' is stored also in Masterdata
$cordovaSQLite.execute(db,
"CREATE TABLE IF NOT EXISTS "
+ tableName + "(id integer, data BLOB)"
);
然后我在这个 table 中插入数据并查询:
"INSERT INTO " + tableName + " (id, data) VALUES (?,?)", parameters
// parameters = [0, base64_imageData_Str]
结果
结果是我注意到加载时间显着增加,即使存储了多个图像(因此有多个 tables)。在我看来,这是有道理的,因为我们可以使用 Masterdata 过滤掉所选相册 id
,然后只加载一张 table.
中的图像
我的问题是:
- 这是不好的、好的还是好的做法?
- 拥有大量 tables 是否有缺点(例如,如果我有 1000 张图像,我将有 1000 tables 使用此设置)
- 如果这是不好的做法,推荐的更好的方法是什么?
将每个 blob 存储在其自己的 table 中绝对 不是 要走的路。我认为这篇文章是在推荐你的第一种方法,应该没问题,只是你的查询是错误的。
SELECT Masterdata.id, ImagesData.data
FROM ImagesData, Masterdata
WHERE Masterdata.album = 'some name'
这将 Masterdata
中的一行与 ImagesData
中的 每一行 连接起来,即使 ImageData
不属于 Masterdata
。您需要添加一个连接条件:
...
WHERE Masterdata.album = 'some name' AND ImageData.id = Masterdata.id
或者更好的是,使用显式连接语法:
SELECT Masterdata.id, ImagesData.data
FROM Masterdata
INNER JOIN ImagesData ON ImagesData.id = Masterdata.id
WHERE Masterdata.album = 'some name'
还要确保 Masterdata.id
和 ImagesData.id
有索引。
好吧,如果它的图像只是图像,为什么不直接将图像作为图像存储在目录中,并在数据库中包含该图像的名称和哈希值。这将使您能够进一步减少加载时间。
哈希将让您将来检查服务器上是否发生了更新。 Watsapp 和其他 Messenger 就是这样做的。
将其保存在受保护的应用程序目录中将确保没有人可以访问。
如果文件太多则考虑分成文件夹->子文件夹->文件。
希望对您有所帮助。
我正在使用这个 SQLite Plugin 作为移动应用程序来享受 'unlimited' 存储限制。基本上我有 base64 imagedata
并且需要将其存储在数据库中。
此外,我还有一些其他 tables 和一个 Masterdata,其中存储了主键以及一些附加信息,例如 albumName
.
使用外键建立关系
为了应对数据库的关系方面,我最初使用外键声明并创建了 table 如下(为简单起见,只显示了两个 table):
// Master Data
$cordovaSQLite.execute(db,
"CREATE TABLE IF NOT EXISTS \
Masterdata(\
id TEXT primary key, \
albumName TEXT, \
favorite INTEGER\
)"
)
// Images
$cordovaSQLite.execute(db,
"CREATE TABLE IF NOT EXISTS \
ImagesData(\
id TEXT, \
data BLOB, \
FOREIGN KEY(id) REFERENCES Masterdata(id)\
)"
)
然后,当我只想加载特定相册的图像时,我 运行 查询:
SELECT Masterdata.id, ImagesData.data FROM ImagesData, Masterdata WHERE Masterdata.album = (?) ["Some album name"]
这工作正常(一切正常加载),但我立即注意到它在处理大型数据集时变慢了。这是有道理的,因为 base64 字符串的存储空间很大。
将 Blob 存储在单独的表中
所以我读了这个 post, 如果您的数据包含 BLOB,建议考虑将每个 BLOB 存储在单独的 table 中。
我编码如下:
// tableName in the form of 'id'_imagesData
// 'id' is stored also in Masterdata
$cordovaSQLite.execute(db,
"CREATE TABLE IF NOT EXISTS "
+ tableName + "(id integer, data BLOB)"
);
然后我在这个 table 中插入数据并查询:
"INSERT INTO " + tableName + " (id, data) VALUES (?,?)", parameters
// parameters = [0, base64_imageData_Str]
结果
结果是我注意到加载时间显着增加,即使存储了多个图像(因此有多个 tables)。在我看来,这是有道理的,因为我们可以使用 Masterdata 过滤掉所选相册 id
,然后只加载一张 table.
我的问题是:
- 这是不好的、好的还是好的做法?
- 拥有大量 tables 是否有缺点(例如,如果我有 1000 张图像,我将有 1000 tables 使用此设置)
- 如果这是不好的做法,推荐的更好的方法是什么?
将每个 blob 存储在其自己的 table 中绝对 不是 要走的路。我认为这篇文章是在推荐你的第一种方法,应该没问题,只是你的查询是错误的。
SELECT Masterdata.id, ImagesData.data
FROM ImagesData, Masterdata
WHERE Masterdata.album = 'some name'
这将 Masterdata
中的一行与 ImagesData
中的 每一行 连接起来,即使 ImageData
不属于 Masterdata
。您需要添加一个连接条件:
...
WHERE Masterdata.album = 'some name' AND ImageData.id = Masterdata.id
或者更好的是,使用显式连接语法:
SELECT Masterdata.id, ImagesData.data
FROM Masterdata
INNER JOIN ImagesData ON ImagesData.id = Masterdata.id
WHERE Masterdata.album = 'some name'
还要确保 Masterdata.id
和 ImagesData.id
有索引。
好吧,如果它的图像只是图像,为什么不直接将图像作为图像存储在目录中,并在数据库中包含该图像的名称和哈希值。这将使您能够进一步减少加载时间。 哈希将让您将来检查服务器上是否发生了更新。 Watsapp 和其他 Messenger 就是这样做的。
将其保存在受保护的应用程序目录中将确保没有人可以访问。
如果文件太多则考虑分成文件夹->子文件夹->文件。
希望对您有所帮助。