2013-07-25 70 views
9

我有一些数据哪些列是动态的,列数据的数量可以随时增加/减少。所以我打算将它们按行存储而不是列格式。将列数据作为行存储的最佳方式MS SQL

我已经放置了列的主表,它指出了列使用的数据类型。我画下主表,供您参考

CID  Name   Type 
1  Speed   Double 
2  Input1  Bool 
3  Message  String 
....... 
....... 

现在我想到两个方法来存储这个动态列数据 第一种方式是

CID  Data_bool  Data_String  Data_Double 
1  NULL   NULL    12 
2  True   NULL    NULL 
3  NULL   test    NULL 
1  NULL   NULL    5 
1  NULL   NULL    15 

方式二是有一个一般性的VARCHAR列每个值作为字符串存储在那里,所以它看起来像

CID  Datas 
1  12 
2  True 
3  test 
1  5 
1  15 

如果你看一下视图的数据库规范化点,则第二种方式似乎很好。但是我认为它会在数据检索中产生问题。因为我想过滤数据,如“速度> 10”。所以,如果我去第二种方式(我将所有的价值存储为字符串),我认为表达式将需要更多的时间来评估 如果我第一次的表达方式,然后首先我需要确定我需要评估的列表达。防爆。为表达速度> 10,首先我要检查速度是哪种数据类型(字符串,布尔等),然后再次执行“data_double> 10”的表达式

两者都有其自身的缺点。有人可以指出,未来哪种方式可以减少我的头痛。请记住,这张表将在后期增加数百万条记录。

我很欣赏你的观点和时间。谢谢。

+0

经过思考所有的可能性,我决定以我的第一种方式去。我知道它没有正常化,但我认为如果我进行正常化,那么表现将是一个大问题。我确定(带着沉重的心情)HD空间,而不是优化所有查询以获得更快的性能。该表是所有计算报告的核心。 – user867198

回答

1

一种方法可能是对您感兴趣的每种数据类型使用一张表。每个表中只有两个字段。一个int型PK和一个对应类型的列来存储数据。在主表中,您可以只有一个int类型的FK链接到特定类型表之一,另一个tinyint类型字段可以决定FK属于哪个子表。

主表

ID INT PK

VALUEID INT非空

类型TINYINT非空

子表(一个或多个)

ID INT PK

数值字符串不为空

ValueID从子表到主表的FK。可以为其他类型创建类似的子表。

+0

你不觉得这会让查询变得困难吗?首先,我需要找到哪个表进行连接,然后应用连接。我认为动态SQL也将在这里发挥作用。 – user867198

+0

您可以创建一个单一的视图,'LEFT JOIN'将所有的子表与主表关联起来。这将为视图中的每个子表创建一个列,就像您在问题中发布的第一个表结构一样。 – dotNET

2

我不确定你是如何访问数据的,也许SQL_Variant可能是一个选项结合SQL_VARIANT_PROPERTY

Declare @a table(id int, cont sql_variant) 
insert into @a select 1,'test' 
insert into @a select 1,Cast('20130101' as DateTime) 
insert into @a select 1,Cast('20130201' as Datetime) 
insert into @a select 1,Cast(1 as Bit) 
insert into @a select 1,Cast(0 as Bit) 
Select * from 
(
Select * from @a 
where SQL_VARIANT_PROPERTY(cont,'BaseType')='datetime' 
) x 
Where cont>Cast('20130101' as DateTime) 
+0

我是这个SQL_Variant类型的新手。看起来很有希望,但是一旦我的表大小变大,您认为“SQL_VARIANT_PROPERTY(cont,'BaseType')='datetime'”会花费更多时间吗?除此之外,它真的很酷 – user867198

+0

A不能给出一个关于性能的坚实答案。由于'(sql_variant_property([cont],'BaseType'))'是非确定性的,所以你不能在一个计算列上创建一个索引,所以我希望在很多数据上都会出现性能问题。因为在我的情况下,行被其他条件预过滤,并且SQL_VARIANT_PROPERTY用于解决fieldmappings我没有在mmy使用情况下的性能问题。 – bummi

0

我知道这并不回答你的问题,这两个选项哪一个更好,但我希望它会有用。

我不会去与这两个选项中的任何一个。我宁愿尝试看看我是否可以将它们放入列中(具有50或100甚至更多列的表格并不罕见)和/或不同的表格。

我建议您安装TFS或Dynamics CRM并查看它们如何存储数据。他们构建了应用程序代码,以便它能够添加/删除数据库中的列,并且它们具有一组跟踪此元数据的表。

如果真的有很多不同的值,我会尝试使用XML数据类型。

+0

你是对的。但我这里的问题是我不知道我会得到多少列数据。我遵循增量模型,后来我不想再次重新创建表以容纳额外的列。 XML也是如此,但是恐怕检索/过滤数据将是一个大问题 – user867198

0

在很多场合我都看到过这类问题,尤其是在应用程序必须允许用户配置字段名称和数据类型的情况下。

这些情况下的解决方案是Key-Value(即2列)表,它们对所有键[显然]都使用varchars,对所有值都使用varchars。

这是一个非常强大的解决方案,它简单易用!

虽然这是最简单和可扩展的选项,但它可能不是最高性能的选项。为每种数据类型设置一个键值表可以提供帮助,但编程起来会有点困难。或者,在同一个表中包含一个Type字段和每个数据类型的列(但不是我最喜欢的,因为这会浪费空间)。

我工作的基于数据库的应用程序使用varchar Value方法,执行时没有明显的缓慢;但是,他们确实只使用简单的基于键的查找操作。您的情况可能会有所不同,特别是如果您对数据执行更复杂的查询。说明明显的,但是,将主键应用于关键字段将提高查询速度。

其他注意事项:

道歉回收我已阅读各种论坛,但我还没有在自己的数据库中使用变量类型。我已阅读:

1)在SQL Server 2005起,用变体类型,而不是一个varchar类型 - 在这种情况下,值列 - 将导致更快的操作,

2)他们不在WHERE子句中不能使用LIKE,

3)OLE DB和ODBC提供程序自动将变量转换为nvarchar(4000)。

+0

我的第一种和第二种方式的结合如何?正如下面的“dotNET”所提到的,我已经将我的第一个表格分区到3个子表(每个表为不同类型),并将值存储在ID和值2列中。然后加入所有的桌子,这将使我获得像我的第一种方式。我认为它看起来不错 – user867198

+0

包括@ dotNET的LEFT JOIN观点想法的组合方法应该适合您的需求;我会去这个。如果不对其进行测试,我认为除了庞大的数据集外,其他性能都不成问题。 –

相关问题