SQL Server 2012和不同的数据类型存储在一个地方

时间:2013-04-03 16:05:55

标签: sql-server sql-server-2012

好的,我不是数据库架构师,所以这个问题完全来自软件开发人员的观点。我目前正在努力获得一个简单的设置数据库,并想知道在SQL服务器中存储不同类型的最有效,最高效的方法是什么。例如,SettingA可以具有布尔值,整数,浮点数或字符串值。存储数据的最有效方法是什么,检索效率最高。

  1. 将所有类型存储在一个字符串的字段中,并让应用程序服务器将其转换为适当的值。

  2. 为不同的类型提供不同的字段,并让应用程序服务器查看哪个字段不为null并使用它(BooleanValue,StringValue,IntValue,FloatValue并且只有一个非null且具有值)

  3. 根据类型将设置规范化为不同的表,如果使用该类型,则仅向表中添加值。 (四个表BooleanValues,StringValues,IntValues,FloatValues与Settings表的外键)。然后SP会返回任何有记录的表。

  4. 性能绝对是我的第一关注点,但空间问题将紧随其后。

4 个答案:

答案 0 :(得分:1)

将设置存储在XML列中。

我指的是单个XML设置文档中项目的所有设置,以便可以一次性检索和更新它们。 Provide a schema降低存储成本并优化查询。然后,数据库将知道设置值的数据类型。

如果您希望查询具有特定设置值的所有项目,可以使用XML索引和/或XQuery查询。

我已经创建了一个SQLFiddle来显示它的外观: http://sqlfiddle.com/#!6/49c34/1

至于索引编制,请查看XML Indexes,特别是Selective XML Indexes

  

选择性XML索引功能允许您仅提升从XML文档到索引的某些路径。在索引创建时,将评估这些路径,并将它们指向的节点碎化并存储在SQL Server中的关系表中。此功能使用Microsoft Research与SQL Server产品团队合作开发的高效映射算法。该算法将XML节点映射到单个关系表,并且只需要适度的存储空间即可实现卓越的性能。

如果通常一起插入和检索设置,我希望这比每个设置使用表行更好,更好。在这种情况下,将它们分成多个位是没有意义的,将这些位分散到表行中,只有在检索它们时才能将它们再次检索并粘合回来。

如果您希望查询一些特定设置或这些特定设置的条件,选择性XML索引将帮助您实现此目的。

何时要小心:

  • 如果项目之间的设置差异很大。因为它们没有共享架构,并且设置文档所需的存储空间变得很大,可能太大了。
  • 如果您需要对设置文档的不同元素进行大范围的查询才能正常运行。因为你可能最终需要很多索引空间。
  • 如果部分设置的更改频率高于其他设置,则可能需要将其分解并单独存储。除此之外,每当有一个位被弄乱时,您就有可能更新整个设置文档。

答案 1 :(得分:1)

我想提出以下建议,专注于高级设计。

首先,看起来你的系统是LOB(业务线系统),而不是数据仓库,所以,当然如果你不同的商业实体,你应该规范化它们遵循NF,通常,第三个NF将足够好。

对于您的具体问题,您有一个字段[SittingA],它可以有4种不同的可能数据类型,我认为您不应该将它们标准化为不同的列或表,因为它只是一个属性,一个提交,你不要我想添加additioinal bussiness逻辑来控制它写入不同的列或表,并在查询时,必须识别查询的位置。

您可以使用Varchar数据类型将它们存储在一列中,但是创建一个计算列,该列对varchar列中的值进行散列,在计算列上创建索引(哈希索引)。您使用存储过程来完成哈希约定和查询。

这可以使您的逻辑简单而整洁。

如果您有其他问题或疑虑,请更新您的问题或发表评论。

答案 2 :(得分:1)

解决方案#2:
您可以使用Isnull链执行类似的操作,以根据某些主键关联将信息拉回。在不知道你的实现的情况下,我不知道这会是多么愚蠢的建议,但它是一种以期望的格式将输入存储在后端的方法。

/*
        Create  Table #test 
                (
                    tID         Int Identity, 
                    StringVal   Varchar(100), 
                    FloatVal    Float, 
                    BoolVal     Bit, 
                    IntVal      Int
                )
*/

Declare @bah Varchar(100)

Set     @bah = 'ValuesToTest'

If      IsNumeric(@bah) = 0
Begin
        If      @bah In ('true','false') --Went with this assumption otherwise you'd get confused between 1 bool and 1 int
        Begin
                Insert  #test (BoolVal)
                Select  Case
                        When    @bah = 'true' Then 1
                        Else    0
                        End
        End
        Else
        Begin
                Insert  #test (StringVal)
                Select  @bah
        End
End
Else    If Floor(Convert(Money,@bah)) <> Ceiling(Convert(Money,@bah)) --Compensate for IsNumeric interpretation of money
Begin
        Insert  #test (FloatVal)
        Select  Convert(Float,Convert(Money,@bah))
End
Else
Begin
        Insert  #test (IntVal)
        Select  Convert(Int,@bah)
End

只有值列的基线将是1个字节一个允许可以为空的值,1个字节用于位列,4个字节用于int列,4个字节用于浮点数,2个字节用于varchar(对于可变长度存储)所以看起来你正在查看15字节的基线。

如果它是一个位或者int(15字节)将是你的存储需要,如果它是一个双倍,如果精度是25或更大,它可能会增加4个字节,varchar将增加等于存储记录的长度。因此,如果您使用非可空varchar,则每个记录最多可节省12个字节(对于可变长度存储,最小为2个字节,对于单个字符值,最小为1个字节)。因此,对于1,000,000条记录,您正在查看有关数据的额外11.5 MB存储空间。

但是,如果您要根据值查找主键,那么使用此解决方案可能会更快,因为在varchar上对bit,int或float索引值进行查找会更快,所以如果在进行查找时,你会知道你要去哪个数据类型会更快走这条路线,因为只要你的列被索引,你就可以忽略所有在a中有值的Null不同的专栏。如果您要获取基于主键的值,请使用单个varchar列,因为其好处可以忽略不计。

答案 3 :(得分:0)

假设数据库服务器和应用程序服务器具有可测量的(> 1ms)延迟,我会选择选项2。 这里有两件事情可做:一起存储在一行中的数据更易于查询,访问速度更快。数据库以块为单位组织存储,并且位于同一行(并且小于块大小,通常为4KB)意味着访问速度更快。

现在,您可能希望设置一个单独的表,其中包含用于设置的主键。 (更少,更小的列导致更快的检索。)通常我建议使用INT作为PK,因为它允许快速外键解析。