【问题标题】:Implementing custom fields in a database for large numbers of records在数据库中为大量记录实现自定义字段
【发布时间】:2014-04-15 14:07:37
【问题描述】:

我正在开发一个应用程序,该应用程序需要用户在联系人表上定义自定义字段。此联系人表可以包含数百万个联系人。

我们正在考虑使用存储有关字段信息的二级元数据表,以及存储实际数据的三级值表。

这是粗略的架构:

CREATE TABLE [dbo].[Contact](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [nvarchar](max) NULL,
    [MiddleName] [nvarchar](max) NULL,
    [LastName] [nvarchar](max) NULL,
    [Email] [nvarchar](max) NULL
)

CREATE TABLE [dbo].[CustomField](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [FieldName] [nvarchar](50) NULL,
    [Type] [varchar](50) NULL
) 

CREATE TABLE [dbo].[ContactAndCustomField](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ContactID] [int] NULL,
    [FieldID] [int] NULL,
    [FieldValue] [nvarchar](max) NULL
)

但是,这种方法会带来很多复杂性,尤其是在导入具有多个自定义字段的 CSV 文件时。目前,这需要为每个单独的自定义字段提供更新/加入语句和单独的插入语句。连接也需要一次返回多行的自定义字段数据

我主张采用这种结构:

CREATE TABLE [dbo].[Contact](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [nvarchar](max) NULL,
    [MiddleName] [nvarchar](max) NULL,
    [LastName] [nvarchar](max) NULL,
    [Email] [nvarchar](max) NULL
    [CustomField1] [nvarchar](max) NULL
    [CustomField2] [nvarchar](max) NULL
    [CustomField3] [nvarchar](max) NULL /* etc, adding lots of empty fields */
)

CREATE TABLE [dbo].[ContactCustomField](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [FieldIndex] [int] NULL, 
    [FieldName] [nvarchar](50) NULL,
    [Type] [varchar](50) NULL
) 

第二种方法的缺点是创建联系人表时必须指定有限数量的自定义字段。我不认为这是一个主要障碍,因为它在导入大型 CSV 文件和返回结果集时肯定会带来性能优势。

对于大量行,哪种方法最有效?第二种技术有什么我没有看到的缺点吗?

【问题讨论】:

  • sparse columns 不正是您所需要的吗?
  • 您当前的示例几乎是 EAV 实现。
  • 谢谢米海。是的,它是一个 EAV 实现,虽然直到现在我还不知道它的正确名称。

标签: sql sql-server database performance custom-fields


【解决方案1】:

Microsoft 专门针对此类问题引入了稀疏列。重点是,在“经典”设计中,您最终会得到大量列,任何特定行的大多数 NULL。此处与稀疏列相同,但 NULL 不需要任何存储。此外,您可以使用 XML 创建列集和修改集。

在性能和存储方面,稀疏列是赢家。

http://technet.microsoft.com/en-us/library/cc280604.aspx

【讨论】:

  • 稀疏列并不能解决表中必须有固定数量的列的问题,而不是实体和属性表之间的一对多关系所提供的灵活性,尽管在性能成本:对于可能经常有空值的列,稀疏列只是一种更好的存储解决方案。
  • @StevePettifer 与 EAV 相比,稀疏列的性能可能要好得多,有利于稀疏列。
  • 稀疏列的问题是动态构建的。
  • @MihaiStancu 空的未使用的列不花钱(好吧,几乎)。
  • @MihaiStancu 确实如此,但 OP 正在考虑选择 EAV 类型模型以提高灵活性或非规范化模型以提高性能。他们是否选择稀疏列可能不是最终解决方案性能的最大决定因素,尤其是在导入大量数据方面。他们可能会选择使用稀疏列,但前提是他们已决定首先使用的模型。
【解决方案2】:

优异的表现。任何“property bag table”方法的查询性能都很有趣而且慢得可笑 - 但是如果您需要灵活性,您可以拥有一个通过编辑器更改的动态表,或者您有一个 property bag 表。所以当你需要它的时候,你就需要它。

但预计性能会很慢。

最好的方法可能是 ContactCustomFields 表,其中包含由编辑器确定的字段。

【讨论】:

  • +1 'property bag' 方法正危险地转向 EAV 模型,它虽然灵活,但通常很慢,开发、维护和使用的背后也有巨大的痛苦,但有时只是没有摆脱它。
  • 我使用相同的数据分析 - 分析运行有参数。可悲的是,这些不是在分析运行之外确定的。除了可怕的财产袋之外没有其他方法可以存储它们;(有时解决方案非常丑陋 - 但唯一可用的。
猜你喜欢
  • 1970-01-01
  • 2012-09-07
  • 2020-09-14
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-22
  • 1970-01-01
相关资源
最近更新 更多