Tsql 将属性存储在整数列中并执行按位操作来检索它们是一个好主意吗?

Tsql 将属性存储在整数列中并执行按位操作来检索它们是一个好主意吗?,tsql,Tsql,在最近的一篇代码杂志文章中,John Petersen展示了如何在TSQL中使用按位运算符,以便在db表的一列中存储属性列表 文章 在他的例子中,他使用一个整数列来记录客户希望通过电子邮件、电话、传真和邮件联系的方式。对于要通过电子邮件联系的客户,查询将如下所示: SELECT C.* FROM dbo.Customers C ,(SELECT 1 AS donotcontact ,2 AS email

在最近的一篇代码杂志文章中,John Petersen展示了如何在TSQL中使用按位运算符,以便在db表的一列中存储属性列表

文章

在他的例子中,他使用一个整数列来记录客户希望通过电子邮件、电话、传真和邮件联系的方式。对于要通过电子邮件联系的客户,查询将如下所示:

SELECT C.*   
FROM   dbo.Customers C  
       ,(SELECT 1   AS donotcontact   
               ,2  AS email   
               ,4  AS phone   
               ,8  AS fax   
               ,16 AS mail) AS contacttypes   
WHERE  ( C.contactmethods & contacttypes.email <> 0 )
AND    ( C.contactmethods & contacttypes.donotcontact = 0 )   
之后,他展示了如何将其封装到表函数中

我的问题是: 1.这是个好主意吗?有什么缺点吗?使用这种存储属性的方法与将属性存储在两个额外的表Customer\u ContactType、ContactType和与Customer表进行连接相比,会遇到什么问题?我想一个问题可能是我的属性列表太长。如果列是整数,那么我的属性列表最多只能是32。
2.当您进入数万条记录时,在查询中执行这些按位操作的性能如何?我猜它不会比任何其他比较操作更昂贵。

如果您希望根据这些位值中的任何一个的值筛选查询,那么这是一个非常糟糕的主意,可能会导致性能问题

此外,根本没有任何需要-只需使用位数据类型

以这种方式使用逐位运算符是一个坏主意的原因是SQL server维护各种列的统计信息以提高查询性能—例如,如果您有一个电子邮件列,SQL server可以大致告诉您电子邮件列中的值为真的百分比,并根据这些知识选择适当的执行计划


然而,如果您有flags列,SQL server将完全不知道一个表中有多少记录与flags和2电子邮件相匹配-它不维护这些类型的索引。如果没有这类信息,SQL server很可能会选择一个糟糕的执行计划。

相反的顺序:了解您的性能的最佳方法是评测

最确切地说,这是一个视情况而定的问题。我个人永远不会把这些东西存储为整数。首先,正如你所提到的,还有转换系数。另一方面,在某个时候,您或其他DBA或其他人必须键入:

Select CustomerName, CustomerAddress, ContactMethods, [etc]
From Customer
Where CustomerId = xxxxx
因为某些数据已损坏,或者因为有人输入了错误的数据,或者其他原因。在我看来,仅仅为了获取基本信息而不得不进行连接和/或函数调用是非常麻烦的


然而,其他人可能会指出您的选择的多样性,或者能够存储多个值类型电子邮件、vs电话、vs传真,无论是在同一列中,或者这种方法的一些其他优势。因此,您确实需要查看您试图解决的问题,并确定哪种方法最适合。

并且不要忘记使用此技术可能导致的维护问题。由于它不是标准的,所有新开发人员可能会被代码弄糊涂,不知道如何正确地调整它。错误将比比皆是,而且很难发现。从中执行报告类型查询也很困难。从维护的角度来看,这种技巧几乎从来都不是一个好主意。它可能看起来很酷,很优雅,但实际上,它是笨重的,而且随着时间的推移很难使用

一个主要的性能影响是,对于以这种方式工作的索引,将不会有一个查找运算符。如果您说contact_email=1,则该列上可能有一个索引,查询将使用该索引;如果你说联系标志&1=1,那么它就不会

**一列只存储一条信息——这是数据库方式**


我不明白——克拉根的回答也说明了这一点,比我的回答早得多。谢谢你的提醒!平心而论,文章作者确实提出了一个要求,即当数据库更改需要最小化时,这是一个选项。啊,是的,关于统计的观点很好。我甚至没有想到这一点。不确定您所说的仅使用位数据类型是什么意思。使用bit数据类型如何解决这个特殊问题?@Mike-我的意思是将每个标志存储在bit列中,但是我承认我在作出判断时没有正确阅读这篇文章!我可能会接受某些实体在标记不适用于该实体的情况下会有空列——也许我可以考虑将标志放入单独的连接表中,但是在它值得之前需要大量的位标志。