我试图在标准SQL数据库中建模系统,我有以下情况。
我有应该存储源位置的表。但有3种位置:URI
,FileSystem Path
,ID
(用于外部服务)。
因此,第一次实施就像是
table my_table (
id ...,
uri VARCHAR(2083),
path VARCHAR(255),
ext_id VARCHAR(255)
)
这种实现有一个缺点:
要解决(尝试)此问题,我添加了一个哈希字段:
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
(索引VARCHAR(2083)
似乎不可能或效率不高)
其他解决方案是合并一列内的所有位置,如下所示
table my_table (
id ...,
location VARCHAR(2083) NOT NULL,
type INT(2) NOT NULL,
hash CHAR(32)
)
这解决了非空问题但我们必须使用VARCHAR(2083)
并添加type
信息作为鉴别器......
我知道这两种解决方案都不是规范化,但性能是优先考虑的因素。该表将被大量使用(80%读取 - 写入率为20%)。
有任何建议吗?
PS:我无法使用任何特定的数据库供应商功能或触发器/存储过程。
编辑:选择解决方案:
table my_table (
id ...,
location VARCHAR(255),
type SMALLINT
)
经过数据分析后,我发现URI超过255是非常罕见的情况。我的实际数据模型(在此新模型之前)将URI存储在VARCHAR(255)
上,因此对我来说没有回归。
我计划实施网址缩短服务来管理1%的情况,其中URI> 255。
我不希望在1%的用例中容忍99%的常用用法。
VARCHAR(2083)
呢?一个原因是 MySQL 引擎无法在UNIQUE constraint
上设置VARCHAR(2083)
。
我认为(可能是错误的)VARCHAR(255)
索引就足够了,所有数据库供应商都应该正确管理它。
答案 0 :(得分:1)
合并所有列似乎没问题。您可以使用参考表来查找所使用的位置类型。因此,您可以在合并表中使用typeid,并且无论位置的类型如何,都将填充位置。不知道你从哈希中获得了多少优势。
表my_table( ID ..., location VARCHAR(2083)NOT NULL, typeId INT(1)NOT NULL - > FK引用location_Type )
table location_Type( typeId INT(1)NOT NULL, typeName VARCHAR(100)NOT NULL )
也忘了回答你对使用VARCHAR(2003)的疑问。 VARCHAR列是可变长度列。因此,当您将列创建为VARCHAR(50)并使用值“ABC”填充它时,仅存储5个字节,数据长度为2个字节,值为“ABC”时为3个字节。所以它不会占用额外的空间。