不要重新发明轮子,尤其是当你试图替换的那个已经是圆形的时候。
因此,让我们看看现有的轮子与您尝试重新发明的轮子相比如何。
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 等键值对数据存储时,情况就不同了。
总而言之,对于每行属性方法有很多话要说,如果你可以通过使用几列来做同样的事情,那么真的没有任何优势。属性表在您实际需要时很有用,例如未知数量的(动态)属性会浮现在脑海中,但在您的情况下,我会保留自然解决方案。