过去几天我一直在修补SQLite3,它似乎是一个不错的数据库,但我想知道它用于序列化。
我需要序列化一组链接到另一个表的键/值对,这就是我到目前为止这样做的方式。
首先会有项目表:
CREATE TABLE items (id INTEGER PRIMARY KEY, details);
| id | details |
-+----+---------+
| 1 | 'test' |
-+----+---------+
| 2 | 'hello' |
-+----+---------+
| 3 | 'abc' |
-+----+---------+
然后会有每个项目的表格:
CREATE TABLE itemkv## (key TEXT, value); -- where ## is an 'id' field in TABLE items
| key | value |
-+-----+-------+
|'abc'|'hello'|
-+-----+-------+
|'def'|'world'|
-+-----+-------+
|'ghi'| 90001 |
-+-----+-------+
这个工作正常,直到我注意到每个表都有一个千字节的开销。如果我只处理一些项目,这是可以接受的,但我需要一个可以扩展的系统。
不可否认,这是我第一次使用与SQL相关的任何东西,所以也许我不知道应该使用什么表,但是我找不到任何“子”的概念。表“或”struct“数据类型。从理论上讲,我可以将键/值对转换为类似的字符串,“abc | hello \ ndef | world \ nghi | 90001”并将其存储在一列中,但这让我想知道是否会破坏使用数据库的目的首先,如果我要将我的结构转换成可以轻松存储在平面文件中的东西。
我欢迎任何人提出任何建议,包括更适合此类序列化目的的不同库的建议。
答案 0 :(得分:2)
您可以在创建数据库之前,或在创建第一个表之前,或在执行PRAGMA page_size = 512;
语句之前尝试VACUUM
。 (手册有点矛盾,也取决于sqlite3版本。)
我认为以高速率动态创建表格也很少见。你正在规范你的模式是好的,但是列可以依赖主键,而重复组是标准化程度较低的标志,外键在合理的模式中重复是正常的。也就是说,我认为您很可能只需要一个键/值对表,其中一列标识客户端实例。
请记住,平面文件也有分配单元开销。观察创建单字节文件时会发生什么:
$ cat > /tmp/one
$ ls -l /tmp/one
-rw-r--r-- 1 ross ross 1 2009-10-11 13:18 /tmp/one
$ du -h /tmp/one
4.0K /tmp/one
$
根据ls(1)
它是一个字节,根据du(1)
它是4K。
答案 1 :(得分:1)
不要为每件物品制作一张桌子。那是错的。类似于在程序中为每个项目编写一个类。为所有项目创建一个表,或者可能存储所有项目的公共部分,其他表格使用辅助信息引用它。帮自己一个忙,阅读数据库规范化规则。
通常,应修复数据库中的表,方法与修复C ++程序中的类相同。
答案 2 :(得分:0)
为什么不将外键存储到items表中?
Create Table ItemsVK (ID integer primary key, ItemID integer, Key Text, value Text)
答案 3 :(得分:0)
如果它只是序列化,即一次性保存到磁盘然后从磁盘进行一次性恢复,则可以使用JSON(recommend C++ libraries列表)。
只需序列化数据结构:
[
{'id':1,'details':'test','items':{'abc':'hello','def':'world','ghi':'90001'}},
...
]
如果要保存一些字节,可以省略id
,details
和items
键并改为保存列表:(如果是瓶颈):
[
[1,'test', {'abc':'hello','def':'world','ghi':'90001'}],
...
]