查询动态连接列的性能优化

Rob*_*Rob 7 sql t-sql sql-server performance database-performance

SQL Server数据库中的当前情况

有一个包含以下列的表条目:

  • EntryID(int)
  • EntryName(nvarchar)
  • EntrySize(int)
  • EntryDate(日期时间)

此外,应该可以为Entry保存额外的元数据.这些元数据的名称和值应该可以自由选择,并且应该可以在不改变数据库表结构的情况下动态添加这些元数据.每个元数据键可以是以下数据类型之一:

  • 文本
  • 数值
  • 约会时间
  • 布尔值(True/False)

因此,有一个表DataKey来表示具有以下列的元数据名称和数据类型:

  • DataKeyID(int)
  • DataKeyName(nvarchar)
  • DataKeyType(smallint)0:文本; 1:数字; 2:日期时间; 3:比特

在表DataValue中,可以根据元数据键的数据类型插入Entry和DataKey值的每个组合.对于每种数据类型,都有一个可以为空的值列.此表包含以下列:

  • DataValueID(int)
  • EntryID(int)外键
  • DataKeyID(int)外键
  • TextValue(nvarchar)可以为空
  • NumericValue(float)可以为空
  • DateValue(datetime)可以为空
  • BoolValue(位)Nullable

数据库结构图:

在此输入图像描述

目标

目标是检索满足规范的条目列表,如WHERE子句.如下例所示:

假设:

  • 元数据键KeyName1是文本
  • 元数据键KeyName2是DateTime
  • 元数据键KeyName3是数字
  • 元数据键KeyName4是布尔值

查询:

... WHERE (KeyName1 = „Test12345“ AND KeyName2 BETWEEN ’01.09.2012 00:00:00’ AND
’01.04.2013 23:59:00’) OR (KeyName3 > 15.3 AND KeyName4 = True)
Run Code Online (Sandbox Code Playgroud)

目标是以非常有效的方式执行这些查询,同时使用大量数据

  • 条目数> 2.000.000
  • 50和100之间或大于100的数据键数
  • 每个条目至少指定一个值的子集,或者也可以是每个键的值(2.000.000*100)

问题

构建查询时出现第一个问题.通常,查询需要具有可以在WHERE子句中使用的列的集合.在这种情况下,查询中使用的列也是表DataKey中的条目,以便能够动态添加元数据而无需更改数据库表结构.在研究期间,已经发现在运行时使用PIVOT表技术的解决方案.但事实证明,当数据库中存在大量数据时,此解决方案非常慢.

质询

  • 是否有更有效的方法或结构来保存数据用于此目的?
  • 如何满足上面列出的要求,同时还要考虑查询时的性能和时间消耗?

这是一个sql小提琴与描述的数据库结构和一些示例数据:http://www.sqlfiddle.com/#!3/d1912 / 3

pod*_*ska 6

实体属性值设计中的一个基本缺陷(这就是您所拥有的)是高效和高效的查询难度.

用于存储数据的更有效的结构是放弃EAV并使用规范化的关系形式.但这必然涉及在数据结构发生变化时改变数据库的结构(这应该是不言而喻的).

您可以放弃TextValue/NumericValue/DateValue/BoolValue字段并将其替换为单个sql_variant列,这会略微降低查询复杂性,但基本问题仍将存在.

作为旁注,如果你不得不处理钱,将所有数字存储为浮动将导致问题.