数据库建模 - 具有相同行为但不同类型数据的列

时间:2015-04-21 08:58:56

标签: mysql sql database

我试图在标准SQL数据库中建模系统,我有以下情况。

我有应该存储源位置的表。但有3种位置:URIFileSystem PathID(用于外部服务)。

因此,第一次实施就像是

table my_table (
  id ...,
  uri VARCHAR(2083),
  path VARCHAR(255),
  ext_id VARCHAR(255)
)

这种实现有一个缺点:

  • 不能约束NOT NULL(当使用像MySQL这样的基本SGBD时)

要解决(尝试)此问题,我添加了一个哈希字段:

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
)
  • 如何管理长于255的URI?

经过数据分析后,我发现URI超过255是非常罕见的情况。我的实际数据模型(在此新模型之前)将URI存储在VARCHAR(255)上,因此对我来说没有回归。

我计划实施网址缩短服务来管理1%的情况,其中URI> 255。

我不希望在1%的用例中容忍99%的常用用法。

  • 为什么不保留VARCHAR(2083)呢?

一个原因是 MySQL 引擎无法在UNIQUE constraint上设置VARCHAR(2083)

  • 为什么要删除哈希字段?

我认为(可能是错误的)VARCHAR(255)索引就足够了,所有数据库供应商都应该正确管理它。

1 个答案:

答案 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个字节。所以它不会占用额外的空间。