简体   繁体   English

用于多个模型的数据库设计?

[英]Database design for multiple models?

I have this design. 我有这个设计。

Table models : 桌子models

id - primary key
title - varchar(256)

Table model_instances : model_instances

id - primary key
model_id - foreign key to app_models.id
title - varchar(256)

Table model_fields : model_fields

id - pk
model_id - foreign key to models.id
instance_id - foreign key to model_instances.id
title - name of the field
type - enum [text, checkbox, radio, select, 'etc']

Table model_field_values : model_field_values

instance_id - forein key model_instance.id
field_id - foreign key to model_fields.id
value - text

Also there can be many values for some field (like for multiple select dropdown) 此外,某些字段可能有很多values (例如,多选下拉列表)

The problem is: value is always text field, because I want to store different types of data (text, datetime, integer) and this table contains all values for all instances of all models. 问题是: value始终是text字段,因为我想存储不同类型的数据(文本,日期时间,整数),并且此表包含所有模型的所有实例的所有值。

For example, if I have 10 models and every model has 1000 instances with 10 fields then model_field_values (at minimum) would contain 100000 rows, if some fields are multiple, then it would contain (120000-150000 rows). 例如,如果我有10个模型,而每个模型有1000个实例,其中包含10个字段,则model_field_values(至少)将包含100000行,如果某些字段为多个,则它将包含(120000-150000行)。

SQL's select using value field would be slow. SQL的使用value选择字段会很慢。

Solution 1: 解决方案1:

For every model create new model_field_values like:

model.id = 1, model_field_values_1
...
model.id = 10, model_field_values_10

Solution 2: 解决方案2:

Because model_fields contains all fields for model, we can create model_field_values like this 因为model_fields包含模型的所有字段,所以我们可以像这样创建model_field_values

model_fields for model.id=1 (by primary key): 1 - text, 2 - integer, 3 - datetime, 4 - smalltext model.id = 1的model_fields(通过主键):1-文本,2-整数,3-日期时间,4-小文本

Fields for model_field_values_1: field_1 text, field_2 integer, field_3 datetime, field_4 varchar(256) model_field_values_1的字段:field_1文本,field_2整数,field_3日期时间,field_4 varchar(256)

This solution is not good for fields with multiple values, because every multiple value should have another table with link to the row in model_field_values_1, but it is good for searching through database because mysql would use native datatypes in where clauses (not text fields). 该解决方案不适用于具有多个值的字段,因为每个multiple值都应具有另一个表,该表具有链接到model_field_values_1中的行的链接,但是它对数据库的搜索非常有用,因为mysql会在where子句(而非文本字段)中使用本机数据类型。

May be I miss something? 可能我想念什么吗? May be there is a better design? 可能会有更好的设计?

This database would be used in crm-system, where user can create different model with many instances in these models, so I can not preconfigure all tables with all columns. 该数据库将在crm系统中使用,在该系统中,用户可以使用这些模型中的许多实例创建不同的模型,因此无法对所有具有所有列的表进行预配置。

Note: 200,000 rows (two tenths of a megarow) is, in the usual operation of MySQL, a medium sized table. 注意:在MySQL的常规操作中,200,000行(兆行的十分之二)是一个中等大小的表。 It's generally possible to index such a table fairly efficiently. 通常可以相当有效地为这样的表建立索引。 http://use-the-index-luke.com/ http://use-the-index-luke.com/

That being said, I think I understand your problem. 话虽如此,我我理解您的问题。 It is, in the jargon of object-oriented design, polymorphism. 在面向对象设计的术语中,它是多态。

You have this model_field_value table, containing 您有此model_field_value表,其中包含

 instance_id
 field_id
 value

Your problem is, the value's native data type is sometimes VARCHAR(255) , sometimes DATETIME or maybe TIMESTAMP , and sometimes INT . 您的问题是,值的本机数据类型有时是VARCHAR(255) ,有时是DATETIMETIMESTAMP ,有时是INT

And you'll sometimes need to do queries like this one 而且有时您需要执行类似这样的查询

 SELECT fv.instance_id
   FROM model_field_value fv
  WHERE fv.field_id = something
    AND fv.value >= '2017-01-01'
    AND fv.value <  '2018-01-01'

to find DATETIME values that happened in calendar year 2017. For example. 查找在2017日历年中发生的DATETIME值。例如。

This is generally a pain in the neck with key/value storage like what you need. 像您需要的那样,键/值存储通常会给您带来麻烦。 For a query like my example to be sargable , you need to be able to put an index on a DATETIME column. 对于像我的例子查询要优化搜索 ,你需要能够把指数上DATETIME列。 But if you don't have such a column, you can't index it. 但是,如果您没有这样的列,则无法为其编制索引。 Duh. 咄。

Here's a suggestion. 这是一个建议。 Give your table these columns. 给您的表这些列。

 instance_id      INT pk fk
 field_id         INT pk fk
 value            VARCHAR(255)  a text representation of every value.
 value_double     DOUBLE        a numeric representation of every numeric value, or NULL
 value_ts         TIMESTAMP     a timestamp value if possible, or NULL

This table will contain redundant data, and you'll have to be very careful when you're writing it to make sure it's correct. 该表将包含冗余数据,并且在编写时必须非常小心以确保其正确。 But you will be able to put indexes on the value_ts and value_double columns, so you can make those kinds of queries sargable. 但是您将能够在value_tsvalue_double列上放置索引,因此可以使这类查询成为可查询的。

Just an idea. 只是一个主意。

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

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