最佳实践,具有 150 多个列的 MySQL 表,许多为空

tur*_*ire 5 mysql performance database-design query-performance

我有一个表存储了数千个属性的属性数据,所有属性都来自一个提要。(每天至少更新一次)。

我当然不是数据库专家,希望得到一些有关构建属性表的最佳方法的指导。挑战在于每个属性都有很多可能包含也可能不包含的属性。每个属性值都可能是唯一的,因此关系表似乎不会提供任何好处。

目前,我对该表的计划很简单,即创建一个包含许多可能为 NULL 的列的宽表。例如:

id - int(not null)
date - datetime(not null)
attribute1 - varchar(null)
attribute2 - varchar(null)
attribute3 - int(null)
attribute4 - bool(null)
ect..
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来设置它?每个属性都与该属性唯一关联,因此将它们全部保存在一个表中对我来说很有意义。

当该表中存在数千条记录时,即使大多数列都是 NULL,有那么多列会导致我出现问题吗?每天,我都需要在这个表上选择几个选择查询,每次返回数百到数千条记录。

非常感谢有关研究内容的任何建议或方向!

Mar*_*cci 4

考虑一个Entity-Attribute-Value设计。一般概念是将所有数据放入一个非常长、窄的表中,该表可能采用以下形式:

CREATE TABLE dbo.PropertyAttributes
(
PropertyID   INT NOT NULL
             REFERENCES dbo.Properties(PropertyID),
AttributeID  INT NOT NULL
             REFERENCES dbo.Attributes(AttributeID),
StringValue  NVARCHAR(1024),
NumericValue DECIMAL(16,4),
DateValue    SMALLDATETIME,
ModifiedDate SMALLDATETIME NOT NULL
             DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (PropertyID, AttributeID)
);
Run Code Online (Sandbox Code Playgroud)

然后存储有关属性的元数据。至少你需要这样的东西:

CREATE TABLE dbo.Attributes
(
AttributeID INT PRIMARY KEY,
PropertyID  INT NOT NULL 
            REFERENCES dbo.Properties(PropertyID),
[Name]      NVARCHAR(32) NOT NULL UNIQUE,
DataTypeID  TINYINT NOT NULL -- 1 = string, 2 = numeric, 3 = date
);
Run Code Online (Sandbox Code Playgroud)

采用这种方法有一些好处,因为当数据中出现新属性时,您不必修改数据库结构来容纳数据,也不必构建新查询来获取您创建的新列。

与生活的其他方面一样,这些好处也伴随着权衡。创建非常宽的视图需要您对Pivot表进行操作,这可能是一个昂贵的查询。

Aaron Bertrand 在这里发了很多帖子,描述了他在 2009 年使用这种方法的经验。今天仍然值得一读。

MDCCL 建议检查属性并可能分解最相关的属性,这是一个很好的建议,将最常用的属性移至基本 Properties 表中,以便减少 EAV 表的旋转频率。