0

我正在尝试围绕 SQLite 数据库创建一个包装器,以允许从 .net 应用程序进行无模式访问。这个想法是让每个实体简单地作为一个集合或属性值对。

优先考虑的是开发人员的简单性和易用性,而不是性能,但我不想完全忽略内存使用和磁盘读取时间。

我的包装器的体系结构意味着至少将在第一个查询中读入所有主键(然后缓存),但是稍后可以根据需要读入其他属性。

问题是,最好为每个属性名称创建(在运行时)一列,并拉入与请求的属性对应的列,还是为每个属性创建一个记录,并拉入请求的属性的记录。

由于应用程序的本质,我不会提前知道将读取哪些订单属性以及是否会读取所有属性。

4

1 回答 1

0

不要重新发明轮子,尤其是当你试图替换的那个已经是圆形的时候。

因此,让我们看看现有的轮子与您尝试重新发明的轮子相比如何。

1)现有的轮子(带列的表格)我们有Entity一个结构如下的表格:

id    INTEGER PRIMARY KEY
attr1 INTEGER
attr2 REAL -- this holds a date
attr3 TEXT
attr4 TEXT

2) 重新发明的轮子,属性表假设我们将EntityAttributes为此创建一个表,我们将保存从Entity1) 开始的所有属性,但问题是它应该是什么样子?我们是否应该将TEXT其用作所有属性值的类型并处理应用程序中的来回转换?然后表格可能如下所示:

entity_id  INTEGER
attr_name  TEXT
attr_value TEXT
           PRIMARY KEY(entity_id, attr_name)

这实际上并没有那么大的戏剧性,因为 Sqlite 在内部将所有内容都存储为 TEXT,但是对于任何普通的 RDBMS 来说,这是一个巨大的损失。

另一种方法是使用支持多种类型的复杂属性表。这可能看起来像:

entity_id  INTEGER
attr_name  TEXT
attr_int   INTEGER
attr_real  REAL
attr_text  TEXT
           PRIMARY KEY(entity_id, attr_name)

还有另一种可能性,使用具有代理键的对(entity_id,entity_name)的主表和每个数据类型的表(其具有主属性表中的代理键值作为PK),但这也变得太非常适合这个讨论。

最重要的是,从一开始就存在我们在挑选车轮时需要解决的问题。

现在让我们继续讨论一下性能。一行中的所有值通常彼此相邻(或接近)存储,因此 IO 成本通常很低。这不能说是多行,尤其是如果它们不是一个接一个地插入的话。您始终可以重新索引数据库文件以优化访问,但如果没有一个接一个地创建行,这将无济于事。
您的解决方案的另一个缺点是它实际上需要比自然解决方案更多的存储空间(不是很多,但仍然更多)。

到现在还好吗?怎么样:您有以下简单的 SQL 查询:

SELECT id, attr1, attr2
  FROM Entity
 ORDER BY attr1;

尝试通过使用每行属性方法来做同样的事情,看看它是多么容易。这只是一个例子,还有很多其他的。

与传统的 RDBMS 相比,属性表解决方案在您的情况下看起来更糟(一次是因为它们在将一行的列值保持在一起方面做得更好,另一次是因为它们支持与 Sqlite 不同的真正不同的类型)。当使用 Redis 等键值对数据存储时,情况就不同了。

总而言之,对于每行属性方法有很多话要说,如果你可以通过使用几列来做同样的事情,那么真的没有任何优势。属性表在您实际需要时很有用,例如未知数量的(动态)属性会浮现在脑海中,但在您的情况下,我会保留自然解决方案。

于 2011-09-02T20:34:07.477 回答