我想我有个问题,伊夫是最好的选择。
我正在计划我的桌子如下。
motherboard_id | model_name
int | varcharmotherboard_id | model_name
----------------------------
1 | Asus Rampage
2 | Intel 3X
3 | Gigabit 22Pattribute_id | attribute_name | attribute_type
int | varchar | enum('str','int','float')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 | strattribute_id | motherboard_id | value
int | int | intattribute_id | motherboard_id | value
-----------------------------------------
1 | 1 | 1
2 | 1 | 16384
1 | 2 | 1
2 | 2 | 32,768
1 | 3 | 2
2 | 3 | 8192attribute_id | motherboard_id | value
int | int | varcharattribute_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 2attribute_id | motherboard_id | value
int | int | floatattribute_id | motherboard_id | value
------------------------------------------
4 | 1 | 250.2
4 | 2 | 250.2
4 | 2 | 110.5我必须查询所有属性(使用WHERE子句)。例如-
找到重量>150克和max_ram>16M的所有主板
因此,我需要查询属性表,并发现int和weight中的max_ram是浮点数。所以,我必须和motherboard一起加入motherboard_attribute_int和motherboard_attribute_float
有办法这样做吗?
是否有更好地为这类数据服务的替代数据库设计?
发布于 2016-12-26 05:09:54
您真正想要的是一个满是可空字段的表,EAV很难得到正确的处理,使用EAV您实际上需要三列,而不是6列。现在只为您的需要添加可空列要容易得多。
因此,是否应该存在一个具有20或30列的表的性能和可伸缩性问题?当我做了一个30列的表时,我换了什么呢?
你拿什么做交易?没什么真正的。与传统的宽表格式相比,使用EAV格式解释和诊断性能和可伸缩性问题要困难得多。实际上,您最终只会得到具有大量空值的表,这些表只需要很好的索引就可以快速找到所需的内容,这比使用EAV要容易得多。
从perf和maint的角度来看,每种数据类型运行1 EAV表与您之前描述的five+列设计一样可怕。你真的不想这么做。您确实希望将许多可空列添加到一个宽表中。你在朝自己的脚开枪,在开始之前问我们怎么包扎它。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
)就是这样。不再有EAV了。如果需要将其用作浮点或int,则在应用程序中这样做。
我还有一些其他的建议,如果你只是一心想用EAV来追踪细节,比如把所有的套接字位移到EAV上,但是相信我,当我告诉你这会比我给你的东西乏味得多。这种格式允许您搜索所需的详细信息(如在选择用户界面中),并允许您在获得一个非常大的表后为通常搜索的功能创建索引。我建议的唯一索引是板名、套接字类型和计数,以及查找的ID。在将系统加载到实际数据之后,我会索引其他所有内容。
EAV模型现在确实不适合这个业务模型,因此,没有看到实际的EAV模式意图,我建议您按照我前面描述的样式来处理它,忽略列的宽度。
到目前为止,我所描述的方法是每个记录大约500个字节,这是相对较小的。单靠指数是很难维持的。
我希望这能帮助您重新考虑问题设计的方法,而我们作为一个社区也一直乐于帮助您充实细节。
https://dba.stackexchange.com/questions/159121
复制相似问题