简体   繁体   English

数据库设计-哪个更好?

[英]Database design - which would be better?

I have multiple tables. 我有多个桌子。

They all have the following fields in them: 它们都具有以下字段:

item_title | item_description | item_thumbnail | item_keywords

Would I be better off having a single items_table with an extra item_type field and then joining with the respective table, or just keep them all in separate tables? 我会最好有一个带有额外item_type字段的单个items_table,然后再与相应的表联接,还是只将它们全部放在单独的表中?

Depends on the context. 取决于上下文。 If your items have very little differentiation and you're certain you're not going to have a scenario in 6 months, 12 months, 2 years where you need items separated, then go the route of one generic “items” table. 如果您的物料差异很小,并且确定在6个月,12个月,2年内不会出现需要将物料分开的情况,则可以使用一个通用的“物料”表。 If a particular item type does have specific requirements, then you can create a separate table that contains this data and create a LEFT JOIN when querying to include the extra data. 如果特定项目类型确实有特定要求,那么您可以创建一个包含此数据的单独表,并在查询以包括额外数据时创建“ LEFT JOIN

I'd also suggest looking at other database types. 我还建议您查看其他数据库类型。 Judging from your scenario (lots of item types with little variance in the data stored) I think you may benefit from a document-based database engine like MongoDB rather than a relational data-based database engine like MySQL. 从您的方案(很多项目类型,存储的数据几乎没有差异)来看,我认为您可能会受益于基于文档的数据库引擎(如MongoDB),而不是基于关系数据的数据库引擎(如MySQL)。

OK, so the tables share fields. 确定,因此表共享字段。 Do they also share constraints 1 ? 他们也共享约束 1吗?

  • If yes, then go ahead and merge them together. 如果是,则继续将它们合并在一起。
  • If not, you may keep them separate, of may merge them together, depending on what kind of tradeoff you are willing to make. 如果不是,则可以将它们分开, 也可以将它们合并在一起,这取决于您愿意进行哪种权衡。

For example, if tables have separate foreign keys, you may keep them separate, or you may merge them into a single table, but keep FKs separate: 例如,如果表具有单独的外键,则可以将它们分开,也可以将它们合并到一个表中,但将FK分开:

item_title
item_description
item_thumbnail
item_keywords
table1_id REFERENCES table1 (table1_id)
table2_id REFERENCES table2 (table2_id)
...
CHECK (
    (table1_id IS NOT NULL AND table2_id IS NULL ...)
    OR (table1_id IS NULL AND table2_id IS NOT NULL ...)
    ...
)

(NOTE: MySQL Doesn't enforce CHECK, so you'll need to do the equivalent enforcement from a trigger or client code, or use a different DBMS if you can.) (注意:MySQL不强制执行CHECK,因此您需要从触发器或客户端代码中执行等效的强制执行,或者,如果可以的话,请使用其他DBMS。)

I'd need to know more about your database to figure out which is better. 我需要更多地了解您的数据库,以找出哪个更好。

with an extra item_type field and then joining with the respective table, 带有一个额外的item_type字段,然后与相应的表联接,

Never enforce FKs in code, if you can help it. 如果可以帮助, 切勿在代码中强制执行FK。 Even if you merge the tables together, don't merge FKs, instead do something like the above. 即使将表合并在一起,也不要合并FK,而应执行上述操作。 Enforcing FKs in code in the context of the concurrent environment (where multiple clients can try to modify the same data at the same time) is difficult to do correctly and with good performance - it's much better to let the DBMS do it for you. 在并发环境(多个客户端可以尝试同时修改同一数据)的环境中在代码中强制执行FK很难正确性能良好-最好让DBMS为您完成。

BTW, what is item_keywords ? 顺便说一句,什么是item_keywords It it's a comma-separated list of keywords (or similar), you'll need to normalize further and extract the keywords into their own separate table. 它是一个逗号分隔的关键字列表(或类似关键字),您需要进一步规范化并将关键字提取到它们自己的单独表中。


1 Domain (data type and CHECK), key (PRIMARY KEY and UNIQUE) and referential (FOREIGN KEY) constraints. 1域(数据类型和CHECK),密钥(PRIMARY KEY和UNIQUE)和引用(FOREIGN KEY)约束。

I believe that it is good to have as less table as possible. 我认为,尽量减少桌子数量是一件好事。 It is easy to maintain. 易于维护。 It is hard to imagine that if you have 3000 type of item_type . 很难想象,如果您有3000类型的item_type Then, there would be 3,000 different table. 然后,将有3,000个不同的表。 So single table is good idea to me in your case. 因此,就您而言,单桌对我来说是个好主意。 In the future, when you run into situation when you need to separate the table, you can easily do so. 将来,当您遇到需要分离表的情况时,可以轻松地做到这一点。

So the short answer, YES . 简短的答案

If i understand well, you only need to normalize your schema: 如果我了解得很好,则只需要规范化架构即可:

items: 项目:

item_id
item_name
item_description

items_types items_types

item_id
type_id

types 类型

type_id
item_file_name

So this way you can have any number of items with any number of types 这样一来,您可以拥有任意数量的任何类型的商品

Is this you want to do??? 这是您想做的吗???

I would suggest you to use one table for item and one table for type for the following reasons (assume there are 10 types). 由于以下原因,我建议您将一个表用于项目,将一个表用于类型(假设有10种类型)。

  1. I am not sure which programming language you are using. 我不确定您使用的是哪种编程语言。 As a Java developer, i will have to create each entity class for each type if I have multiple tables. 作为Java开发人员,如果我有多个表,则必须为每种类型创建每个实体类。 So i would rather have only one class and have a type as an attribute. 因此,我宁愿只有一个类并具有一个类型作为属性。
  2. When you have to display all of the types in the same page, you will have to execute the select query from all 10 tables for 10 types. 当必须在同一页面中显示所有类型时,将必须从所有10个表中对10种类型执行select查询。
  3. When you introduce a new type, you have to write the code to for the CRUD and Business specific operations. 引入新类型时,必须为CRUD和业务特定的操作编写代码。 The developer will keep on adding the code for every new type. 开发人员将继续为每种新类型添加代码。

Basically, if you have one table for item and one table for type, you won't have to change the database schema and code for each new type you introduce. 基本上,如果您有一个表用于项,一个表用于类型,则不必为引入的每种新类型更改数据库模式和代码。 But if you are sure that, the number of types is less and won't change, you can consider using muiltiple tables. 但是,如果您确定类型的数量较少并且不会更改,则可以考虑使用多表。

Create two separate tables and join them as per your required output. 创建两个单独的表,并根据需要的输出将它们联接起来。

ie> 即>

1.1'st TABLE (master table==>item_type) 1.1'st TABLE(主表==> item_type)

item_type(item_type_id,item_type_name,status) item_type(item_type_id,item_type_name,状态)

2.2'nd TABLE(child table==>item_details) 2.2 nd TABLE(子表==> item_details)

item_details(item_id,item_type_id,item_title,item_description,item_thumbnail,item_keywords) item_details(item_id,item_type_id,item_title,item_description,item_thumbnail,item_keywords)

See more examples.. 查看更多示例。

I feel signle table would be more suitable. 我觉得单人桌会更合适。 It will avoid more joins, complication in program(Code) and errors in compare of multiple tables. 它将避免更多的联接,程序(代码)复杂化以及多个表比较中的错误。 Even it will be better from the management point of view like db clustering etc. 从管理的角度来看,甚至更好,例如数据库集群等。

If you have so many tables which needs to have the same repeated columns then yes it is a good way to create a separate table for the common fields. 如果您有太多需要重复相同列的表,那么可以,这是为公共字段创建单独表的好方法。 This is more efficient if these repeated columns are not fixed and can be changed like adding one more column to the list of common default columns. 如果这些重复的列不是固定的,并且可以像在通用默认列的列表中再添加一个列那样进行更改,则这样做会更有效率。

So how could you do that? 那你怎么做呢?

The idea is to create a seperate table and put the common default columns there. 这个想法是创建一个单独的表,并在其中放置通用的默认列。 This table is like a dummy table ie the columns can be added/deleted as needed. 该表就像一个虚拟表,即可以根据需要添加/删除列。

For example- 例如-

Table - DefaultFields DefaultFields

Columns - item_title | item_description | item_thumbnail | item_keywords item_title | item_description | item_thumbnail | item_keywords item_title | item_description | item_thumbnail | item_keywords

You can then also be able to insert the values in the DefaultFields table dynamically in a loop like: 然后,您还可以像下面这样循环地将值动态插入到DefaultFields表中:

"INSERT INTO DefaultFields (item_table, item_title , item_description,item_thumbnail ,item_keywords) VALUES('"+ field.item_table + "','" + field.item_title + "','" + field.item_description+ "','" + field.item_thumbnail  + "','" + field.item_keywords)");

NOTE: field is the object that holds the values in a table wise loop. 注意:字段是在表明智循环中保存值的对象。

Then further you can alter your tables to create these default fields from DefaultFields table like: 然后,您可以进一步更改表以从DefaultFields表创建这些默认字段,例如:

  "ALTER TABLE " + item_table+ " ADD COLUMN [" + field.item_title + "] Text"

This can be repeated for each table to alter it as needed. 可以对每个表重复此操作以根据需要对其进行更改。

In this design pattern, even if you want to: 在这种设计模式下,即使您要:

1) add one more column or 1)再增加一列或

2) delete pre existing column or 2)删除预先存在的列或

3) change pre existing column name 3)更改现有的列名

Then you can do so in the dummy table and the rest is updated by the ALTER table command in corresponding tables. 然后,您可以在虚拟表中执行此操作,其余的将通过ALTER table命令在相应表中进行更新。

In my opinion... I would say no, never. 我认为...我不会,永远不会。

There is two reason for that: 这有两个原因:

  • You really want to preserve a logical meaning in your database. 您确实想在数据库中保留逻辑含义。 For now it's pretty obvious for you how it's organised. 目前,它的组织方式非常明显。 But in two month (or 1 year), will it be so evident? 但是在两个月(或一年)内,会如此明显吗? If somebody join the project, isn't it easier for him to understand if the different logical block of your app are separated? 如果有人加入该项目,他是否更容易理解您的应用程序的不同逻辑块是否分开? I mean... It's true that a human and a cat are animals. 我的意思是……人和猫都是动物。 Is it still logical to store both of them inside the same box? 将它们都存储在同一个盒子中是否仍然合乎逻辑?

  • Performance. 性能。 The shorter the table, the faster your request will be. 表越短,您的请求就会越快。 The data will still take as much space on your disk. 数据仍会占用磁盘上的空间。 And i don't talk about the comparison for knowing which type of item you are looking for. 而且,我不会谈论要查找哪种类型的比较。 I mean, if you want to select all the pages of your application, just compare the two request: 我的意思是,如果要选择应用程序的所有页面,只需比较两个请求即可:

Multiple tables: 多个表:

Select * from pages_tbl;

Single table: 单桌:

Select * from item_tbl where type = 'page';

What will you gain from this design? 您将从这种设计中获得什么? No performance, no disk space, no readability. 没有性能,没有磁盘空间,没有可读性。 I really don't see a good reason for it. 我真的没有很好的理由。

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

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