Lor*_*oh. 6 mariadb database-design eav
我想我有一个问题,EAV 是最好的选择。
我正在计划我的桌子如下。
motherboard_id | model_name
int | varchar
Run Code Online (Sandbox Code Playgroud)
motherboard_id | model_name
----------------------------
1 | Asus Rampage
2 | Intel 3X
3 | Gigabit 22P
Run Code Online (Sandbox Code Playgroud)
attribute_id | attribute_name | attribute_type
int | varchar | enum('str','int','float')
Run Code Online (Sandbox Code Playgroud)
attribute_id | attribute_name| attribute_type
-------------------------------------------------
1 | form_factor | int
2 | max_ram | int
3 | ram_type | str
4 | weight | float
5 | CPU_socket | str
6 | PCH | str
Run Code Online (Sandbox Code Playgroud)
attribute_id | motherboard_id | value
int | int | int
Run Code Online (Sandbox Code Playgroud)
attribute_id | motherboard_id | value
-----------------------------------------
1 | 1 | 1
2 | 1 | 16384
1 | 2 | 1
2 | 2 | 32,768
1 | 3 | 2
2 | 3 | 8192
Run Code Online (Sandbox Code Playgroud)
attribute_id | motherboard_id | value
int | int | varchar
Run Code Online (Sandbox Code Playgroud)
attribute_id | motherboard_id | value
--------------------------------------------
3 | 1 | DDR3
5 | 1 | LGA2011
6 | 1 | Intel P55
3 | 2 | DDR3
5 | 2 | LGA3011
3 | 3 | DDR2
5 | 3 | Socket 2
Run Code Online (Sandbox Code Playgroud)
attribute_id | motherboard_id | value
int | int | float
Run Code Online (Sandbox Code Playgroud)
attribute_id | motherboard_id | value
------------------------------------------
4 | 1 | 250.2
4 | 2 | 250.2
4 | 2 | 110.5
Run Code Online (Sandbox Code Playgroud)
我将不得不查询所有属性(使用 WHERE 子句)。例如 -
找到所有重量 >150g 且 max_ram>16M 的主板
因此,我需要查询属性表并发现 int 中的 max_ram 和 weight 是一个浮点数。所以,我必须参加motherboard
与motherboard_attribute_int
和motherboard_attribute_float
有没有办法做到这一点?
是否有替代数据库设计可以更好地为此类数据提供服务?
您真正想要的是一个充满可为空字段的表,EAV 很难做到正确,而使用 EAV,您实际上需要三列,而不是 6 列。此时继续添加可空列来满足您的需求会容易得多。
那么拥有 20 或 30 列的表不应该存在性能和可扩展性问题吗?当我制作一个 30 列的表格时,我要权衡什么?
你在权衡什么?真的没什么。与传统的宽表格式相比,EAV 格式的性能和可扩展性问题更难以解释和诊断。实际上,您最终只会得到包含大量空值的表,您只需要良好的索引即可快速找到所需的内容,这比使用 EAV 容易得多。
从性能和维护的角度来看,每种数据类型运行 1 个 EAV 表与您之前描述的五列以上设计一样可怕。你真的不想这样做。您确实只想将大量可为空的列添加到一张宽表中。你是在搬起石头砸自己的脚,然后在开始之前询问我们如何包扎它。EAV 不是您现在想要的设计模式,部分原因是您不了解该模型的工作原理。对您的业务数据进行建模,然后对您的数据库进行建模。
就您而言,您需要一张包含供应商、主板名称/型号等的主板表。我在下面模拟了一个简单的表格。然后,EAV 将与该表一起使用来对“驱动程序下载链接”等很少需要的内容进行建模。将主表视为搜索详细信息,而 EAV 是仅当您在 UI 上显示辅助选项卡时才需要的详细信息。
create table motherboards (
id bigint not null auto_increment
, vendor_name varchar(100) not null -- would also be good as a lookup column to another table, making this an int or bigint instead
, board_name varchar(100) not null
, revision_number varchar(100) null
, cpu_socket_type not null -- can be an int lookup to another table or a text field, I leave this to you based on the schema you want, but either is acceptable, as is an int with an in-app enum lookup
, cpu_socket_count int not null default 1
, ram_socket_type not null -- again, can be one of so many values, you decide the best type of storage
, ram_socket_count tinyint not null default 1 -- here's where things get tricky, it's possible on some systems (enterprise grade) to have different RAM sockets for different reasons, but we skip that because that's a lot of detail. Wait till you have to cross that bridge, mkay?
, northbridge_chipset varchar(100) not null -- this makes the most sense to me, but see the cpu_socket_type comment. There are a handful of common ones, so text may be easier to deal with.
, southbridge_chipset varchar(100) null -- see above
-- This is now the additional details for others
, rear_port_usb tinyint not null default 2
, usb_headers tinyint not null default 0
, upc_number varchar(20) null
, pcie_socket_count tinyint not null default 0
, pcie_x2_socket_count tinyint not null default 0
, pcie_x4_socket_count tinyint not null default 0
, pcie_x8_socket_count tinyint not null default 0
, pcie_x16_socket_count tinyint not null default 0
, sata_headers_count tinyint not null default 0
, pci_socket_count tinyint not null default 0
, isa_socket_count tinyint not null default 0
, rear_port_matrix -- some set of fields to indicate what is on the back panel where people can have access. I would probably either make up a standard "dictionary" of these and do it like an enum/lookup table, or list one per port. Where do you put parallel ports on this lookup list? How many USB are exposed via the backplate? How many USB are exposed on headers on the motherboard?
)
create table motherboards_details (
id bigint not null (fk back to motherboards)
, name varchar(100) not null
, value varchar(100) not null
, create_date datetime not null default CURRENT_TIMESTAMP -- always good to have for later tracking
)
Run Code Online (Sandbox Code Playgroud)
就是这样。不再有 EAV。如果您需要将其用作浮点数或整数,则可以在应用程序中执行此操作。
如果您一心想使用 EAV 来跟踪详细信息,例如将所有这些套接字位移至 EAV,我还有一些其他建议,但请相信我,这将变得比我给出的要乏味得多你。通过这种格式,您可以搜索所需的详细信息(例如在选择器 UI 中),并且可以在获得非常大的表后为常用搜索功能构建索引。我建议的唯一索引是板名称、插槽类型和数量以及用于查找的 ID。在将系统置于实际数据负载下后,我将索引所有其他内容。
EAV 模型目前确实不适合此业务模型,因此在没有看到实际的 EAV 模式意图的情况下,我建议您按照我上面概述的样式来处理它,并忽略列宽度。
到目前为止,我上面概述的方法是每条记录大约 500 字节,相对较小。仅靠索引就很难维护。
我希望这可以帮助您重新考虑问题设计的方法,并且我们作为一个社区始终很乐意帮助您充实细节。
归档时间: |
|
查看次数: |
121 次 |
最近记录: |