【发布时间】:2014-03-20 22:35:04
【问题描述】:
我正在尝试将有关文档的元数据存储到 SQL Server 中。文档存储在文档存档中,并返回一个标识符,这样我就可以通过要求存档按标识符获取文档来取回该文档。
我们的用户希望能够根据不同的元数据搜索此文档。元数据可以是 1 个属性或 5 个,具体取决于文档类型,并且用户应该能够从管理站点创建新的文档类型。
我可以在这里看到两个解决方案。一种是每个文档类型都有自己的元数据表,其中所有元数据属性都是预定义的,如果应该添加一个,则需要创建一个新列。如果创建了新的文档类型,则需要创建新的元数据表。我们的 DBA 会被这样的解决方案吓坏了,而且我也看到了索引的问题。因为如果文档类型有 5 个不同的元数据属性,则需要在搜索中指定其中的 1 个或 4 个来进行搜索。然后我需要为可能的搜索的所有不同组合编写索引。
这是一个例子(虚构)
|documentId | Name | InsertDate | CustomerId | City
| 1 | John | 2014-01-01 | 2 | London
| 2 | John | 2014-01-20 | 5 | New York
| 3 | Able | 2014-01-01 | 10 | Paris
我可以在这里说:
- 给我所有 Name = 'John' 的文件
- 给我所有 Name = 'John' And CustomerId = 5 的文档
- 给我所有文档,其中 InserDate = '2014-01-01' 和 City = 'London'
这将是 3 个不同的索引,然后我没有涵盖所有可能的组合。这不切实际。
所以我正在研究邪恶的“EAV”(反)模式。
因此,我可以将元数据作为行,而不是将元数据作为列。
|documentId | MetaAttribute | MetaValue
| 1 | Name | John
| 1 | InsertDate | 2014-01-01
| 1 | CustomerId | 2
| 1 | City | London
| 2 | Name | John
| 2 | InsertDate | 2014-01-20
| 2 | CustomerId | 5
| 2 | City | New York
| 3 | Name | Able
| 3 | InserDate | 2014-01-01
| 3 | CustomerId | 10
| 3 | City | Paris
在这里创建一个索引 om MetaAttribute och metaValue 很简单,并且已经涵盖了。如果创建了新文档类型,则可以使用该文档类型将新元数据创建到 MetaAttributeTable(包含不同文档类型的所有 MetaAttribute)中。因此,如果添加了新文档类型或将新属性添加到文档类型,则无需创建新表或库。相反,所有 MetaValues 大部分都是字符串 :( 并且查找文档 ID 的 SQL Query 有点复杂。
这是我想出来的。 (在本例中,MetaAttribute 是一个字符串,但它是 MetaAttribute 表的 ID)
SELECT * FROM [Document]
WHERE ID IN (SELECT documentId FROM [MetaData]
WHERE ((MetaAttribute = 'Name' AND MetaValue = 'John')
OR (MetaAttribute = 'CustomerId' and MetaValue = '5'))
GROUP BY [documentId]
HAVING Count(1) = 2)
在这里,我需要询问 Name = 'John' 和 CustomerId = 5。我通过查找 Name = 'John' 和 CustomerId = '5' 的所有记录并将其分组到 documentId 和计数上来做到这一点组中的项目。如果我得到 2,那么 Name = 'John' 和 CustomerId = '5' 对于这个搜索都是正确的。返回 documentId 并使用它来检索有关文档的信息,例如文档存档存储 ID。
应该有一个更好的 SQL 语句,不是吗?
所以我的问题是。有没有比这 2 种更好的方法。EAV 模式是否如此糟糕,以至于我应该坚持第一种方法并拥有一个吓坏了的 DBA 和“一千万个索引”
我们谈论的是一个每月将有大约 10 到 20 百万条新记录的系统,并且包含至少 3 年的数据......因此,这些表将非常大,并且良好的索引对于性能是必不可少的。
最好的问候 马格努斯
【问题讨论】:
-
您有没有想过使用全文搜索而不是多个索引?
标签: sql-server database-design