我试图在标准的sql数据库中建模一个系统,我遇到了以下情况。
我有一个表应该存储源位置。但是有三种位置:URI
,FileSystem Path
,ID
(用于外部服务)。
因此,第一个实现类似于
table my_table (
id ...,
uri VARCHAR(2083),
path VARCHAR(255),
ext_id VARCHAR(255)
)
此实现有一个缺点:
不能约束不为空(当使用基本的sgbd如mysql时)
若要解决(尝试)此问题,请添加哈希字段:
table my_table (
id ...,
uri VARCHAR(2083),
path VARCHAR(255),
ext_id VARCHAR(255),
hash CHAR(32) NOT NULL
)
表示“
hash(uri)
,hash(path)
或hash(ext_id)
,另外有助于索引uri
(索引> cc>似乎不可能或不有效)另一个解决方案是合并一列中的所有位置,如下所示
table my_table (
id ...,
location VARCHAR(2083) NOT NULL,
type INT(2) NOT NULL,
hash CHAR(32)
)
这解决了非空问题,但我们必须使用
VARCHAR(2083)
并添加VARCHAR(2083)
信息作为鉴别器…我知道这两种解决方案都不是标准化的,但性能是优先考虑的。此表将被大量使用(80%读取-20%写入)。
有什么建议吗?
注:我不能使用任何特定的数据库供应商特性或触发器/存储过程。
编辑:选择的解决方案:
table my_table (
id ...,
location VARCHAR(255),
type SMALLINT
)
如何管理超过255的uri?
经过数据分析,我发现uri超过255是非常罕见的情况。我的实际数据模型(在这个新模型之前)将uri存储在
type
上,所以对我来说没有回归。我计划实现一个url shortener服务来管理uri>255的1%的情况。
我不想在1%的用例中限制99%的通用性。
为什么不保持
VARCHAR(255)
?一个原因是mysql引擎无法将
VARCHAR(2083)
设置为UNIQUE constraint
。为什么要删除散列字段?
我认为(可能是错误的)
VARCHAR(2083)
索引已经足够了,所有数据库供应商都应该正确地管理它。 最佳答案
合并所有列似乎很好。您可以将引用表用于所使用的位置类型。因此,可以在合并表中使用typeid,并且不管位置的类型如何,都将填充该位置。不过,我不知道你从散列中得到了多少好处。
我的桌子(
身份证件。。。,
位置varchar(2083)不为空,
typeid int(1)不为空-->对位置类型的FK引用
)
表位置类型(
typeid int(1)不为空,
typename varchar(100)不为空
)
还忘了回答您对使用varchar(2003)的疑问。varchar列是可变长度的列。因此,当您创建一个列作为varchar(50)并用值“abc”填充它时,只存储5个字节,数据长度为2个字节,值“abc”为3个字节。所以不会占用额外的空间。
关于mysql - 数据库建模-具有相同行为但数据类型不同的列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29767482/