在SQLite中读取行与列的相对成本是多少?

时间:2011-09-02 15:05:39

标签: database sqlite database-design database-schema schemaless

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

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

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

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

根据应用程序的性质,我不会事先知道将读取哪些订单属性以及是否将读取所有属性。

1 个答案:

答案 0 :(得分:0)

不要重新发明轮子,特别是当您尝试更换的轮子已经是圆形时。

让我们看看现有的车轮与你试图重新发明的车轮相比如何。

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

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

2)重新发明轮子,属性表 假设我们将为此创建一个表EntityAttributes,我们将保留Entity在1处的所有属性,但问题是它应该如何?我们是否应该使用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等数据存储是另一回事。

总而言之,对于每行属性方法有很多话要说,如果你可以通过使用几个列来做同样的事情,那就没有什么优势了。当你真正需要它时,属性表非常有用,可以想到未知数量的(动态)属性,但在你的情况下,我会坚持使用自然解决方案。