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,有那么多列会导致我出现问题吗?每天,我都需要在这个表上选择几个选择查询,每次返回数百到数千条记录。
非常感谢有关研究内容的任何建议或方向!
考虑一个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 表的旋转频率。