简体   繁体   English

MYSQL和规范化:如何处理许多可选字段?

[英]MYSQL and Normalisation: How to handle lots of optional fields?

I have a profile page with about 20 optional fields on it. 我有一个个人资料页面,上面有大约20个可选字段。 To keep it normalised would I have to create 20 different tables and then do a query with 20 JOINS in it. 为了保持规范化,我必须创建20个不同的表,然后在其中进行20个JOINS的查询。 That seems a bit over the top to me. 这对我来说似乎有点过头了。

Is that the best way to do it? 这是最好的方法吗?

Do you recommend that I keep it normalised? 你建议我保持标准化吗?

A good way to do this (although a bit confusing unless you know what's going on) is using the same design wordpress uses - as far as I remember it was called entity attribute value (Thanks to @Matt Fenwick). 一个很好的方法(虽然有点令人困惑,除非你知道发生了什么)使用相同的设计wordpress使用 - 据我记得它被称为实体属性值(感谢@Matt Fenwick)。 https://stackoverflow.com/tags/eav/info https://stackoverflow.com/tags/eav/info

Basic idea is that, instead of your 20 INNER JOIN -able tables to store odds and ends, you have two tables. 基本的想法是,你有两个表,而不是你的20个INNER JOIN表来存储赔率和结束。 One stores your entity (a post in wordpress' case) and the second stores all your odds and ends - or metadata as WP refers to it. 一个存储您的实体(一个帖子在wordpress'案例中),第二个存储您的所有可能性和结束 - 或者WP指向它的元数据。 Instead of having a column for each data point, you have a column for name, one for value, and one for the ID of the entity that this property applies to. 您没有每个数据点的列,而是有一个名称列,一个用于值,一个用于此属性适用的实体的ID。

This way you save yourself a ton of SQL, headaches during extension and time required to build it to begin with. 通过这种方式,您可以节省大量的SQL,扩展期间的麻烦以及开始构建它所需的时间。 If you ever need to cater for another property, you just bung it in there with the rest - no hacking the schema. 如果您需要为另一个房产提供服务,那么您只需将其与其他房产一起打包 - 不要破坏架构。

Some more detail on WP's database layout (here I'm thinking mostly of the wp_posts and wp_postmeta tables): http://codex.wordpress.org/Database_Description 关于WP数据库布局的更多细节(这里我主要考虑的是wp_posts和wp_postmeta表): http ://codex.wordpress.org/Database_Description

So an example might be (pseudocode, sorry): 所以一个例子可能是(伪代码,对不起):

table: yourEntity
entityID  int, primary key, auto increment
title     varchar

table: yourEntityMeta
entityID  int, non-unique key
name      text
value     text

This way you can have any number of properties for each entity with no restrictions or performance concerns over unused columns with NULL values and 18 more tables that need joining. 这样,您可以为每个实体提供任意数量的属性,对具有NULL值的未使用列和18个需要连接的表没有限制或性能问题。

Hope this helps 希望这可以帮助

Note: one issue with this (pointed out by @ypercube in the comments) is that using this means you can't specify the data type for each attribute, ie a date attribute would be stored as text, as would a boolean or int. 注意:此问题的一个问题(在评论中由@ypercube指出)是使用这意味着您不能为每个属性指定数据类型,即日期属性将存储为文本,如布尔值或int。 You also wouldn't be able to use a foriegn key to link to a table of valid values (thanks to @Catcall). 您也无法使用foriegn键链接到有效值表(感谢@Catcall)。 You would need to consider this carefully before going down this route. 在沿着这条路走下去之前,你需要仔细考虑。

I would just use nullable columns for the optional fields. 我只会将可空列用于可选字段。 The table will get quite large, but so many joins will just degrade your performance, and I cannot find a reason why this fields should be normalized, if they belong to one Object and will be updated together. 该表将变得非常大,但是如此多的连接只会降低您的性能,我找不到这些字段应该归一化的原因,如果它们属于一个对象并且将一起更新。

If the option fields are constants, consider using an ENUM (for 2-20 options), however this method has its own pitfalls. 如果选项字段是常量,请考虑使用ENUM(2-20个选项),但是这种方法有自己的缺陷。

If your primary concern is database normalisation, you should have the separate 'look-up' tables for each option field, even if you have 20 option fields, so that you don't store duplicate data. 如果您主要关心的是数据库规范化,那么即使您有20个选项字段,也应该为每个选项字段分别设置“查找”表,这样就不会存储重复数据。

Also, if you decide to change the options in the future it makes your table a lot easier to maintain in the future. 此外,如果您决定在将来更改选项,它将使您的表在将来更容易维护。

The JOIN statements aren't that bad, and MySQL can support upto 61 tables in one query. JOIN语句也不错,MySQL可以在一个查询中支持多达61个表。 I already explored that topic in this question of mine . 我已经在我的这个问题中探讨了这个话题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM