布尔标志字段的模式设计(数据库体系结构)



背景

该架构适用于附近餐厅的个人应用程序。我正在考虑两种存储单值布尔(true/false)标志值的方法。

我在机器人方面的背景迫使我考虑更小的数据库占地面积。我可能大错特错。

项目

这个应用程序将有餐厅名称和某些单一标志字段。这些固定属性不会很快改变:

选项1:同一张表中的单个标志或与餐厅ID相连的特定1:1属性表

Rest ID  | hasOutdoor | hasDelivery | hasWifi
Rest1    |  1         |  1          |  1     
Rest2    |  0         |  1          |  0

从方案上讲,备选方案1很容易;为每个餐厅提取单独的财产。

选项2:一个具有所有属性的字符串字段

Rest ID | Property
Rest1   |  "111"             
Rest2   |  "010"  

这将有一个小的数据库占用空间,但在编程上非常难以处理。

python中的示例:

PropertySet = ['hasOutDoors', 'hasDelivery', 'hasWifi'] 
for eachChar in Rest1.Property:
if int(eachChar):
PropertySet.pop()

输出:

'hasOutDoors'
'hasDelivery'

选项2的主要缺点:

  1. 代码和数据库对象是混合的。如果在数据库中添加一个新属性,并且需要在代码中进行相同的更改,这可能会导致系统崩溃。

  2. 很难编码(并且处理量很大)"获取所有具有Outdoor属性的Rest"!

是否有更好的存储0/1值的方法,或者选项1是最好的

使用布尔字段。它们的存在是有原因的。你真的认为节省几个字节(可以说你可能没有这样做,因为数据库确实优化了存储)在查询速度方面真的值得权衡吗?

查询数据库比检索所有结果并使用Python限制这些结果要快得多。

数据库比这聪明得多。假设你有20张唱片。其中CCD_ 1为真。如果运行SELECT * from restaurants WHERE hasDelivery。然后(通过适当的索引)它不会从磁盘中读取所有20条记录。它将读取5条记录并返回它们。很明显,我只是有点泛泛和手工。但是请仔细阅读您决定使用的数据库实现。

一句话:用Python进行处理意味着EACH查询必须将整个数据集读取到内存中。这是一项昂贵的手术。对于布尔值设置为true/false的记录的DB查询将只从磁盘上读取这些记录。

首先,字符串不太可能需要更小的存储空间。在直接支持布尔类型的DBMS上,它实际上可能更大1

第二,也是更重要的一点,如果你必须单独搜索、读取或写入任何标志,那么将它们存储在同一个字段中将违反原子性原则,从而违反1NF。这将阻止您对单个标志进行索引,并且通常会使处理数据的方式复杂化。

是否有更好的存储0/1值的方法,或者选项1是最好的?

如果您的DBMS支持布尔数据类型,请选择它。

如果没有,您可能仍然最好对每个单独的标志使用CHAR(1)之类的东西。但是,如果您的存储要求非常严格,并且您确信这样做不会违反1NF,则可以在同一整数字段中将多个标志打包在一起(使用逐位操作)。


1例如,MS SQL Server可以将多个BIT字段打包到同一字节的存储中。相反,字符串中的1个字符至少需要1个字节(根据字符编码,可能需要更多)。即使在"本机"不支持布尔数据类型的DBMS(如Oracle)上,每个"模拟"布尔字段也可能只花费一个字节,这仍然不会更糟

最新更新