Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 具有动态字段的数据库设计:单表与多表-多索引_Design Patterns_Database Design_Database Schema - Fatal编程技术网

Design patterns 具有动态字段的数据库设计:单表与多表-多索引

Design patterns 具有动态字段的数据库设计:单表与多表-多索引,design-patterns,database-design,database-schema,Design Patterns,Database Design,Database Schema,我必须选择一个数据库的结构,该结构将存储具有动态字段的内容类型(例如博客文章、页面、文档、发票、估价等):例如,估价内容类型应包含标题、日期和总价 但是,在这段时间内,这些字段可以添加或删除,因此在1年后,估算持续类型可以有注释字段 这是著名的CMS(例如drupal)提供的一项常见任务,但我想知道获得最佳性能和灵活性的最佳方法是什么:例如,drupal使用一个带有basic字段(例如title)的表,所有辅助字段存储在动态创建的子表中,并使用外键链接到主表: table node | id |

我必须选择一个数据库的结构,该结构将存储具有动态字段的内容类型(例如博客文章、页面、文档、发票、估价等):例如,
估价
内容类型应包含
标题
日期
总价

但是,在这段时间内,这些字段可以添加或删除,因此在1年后,
估算
持续类型可以有
注释
字段

这是著名的CMS(例如drupal)提供的一项常见任务,但我想知道获得最佳性能和灵活性的最佳方法是什么:例如,drupal使用一个带有
basic
字段(例如
title
)的表,所有辅助字段存储在动态创建的子表中,并使用外键链接到主表:

table node
| id | title         | ...
|  1 | First example |
table fields_node_total_price
| id | node_id | value  |
|  1 | 1       | 123.45 |
table fields_node_date
| id | node_id | value    |
|  1 | 1       | 12345677 |
等等

我的观点是,这种方法非常灵活,但很容易陷入性能问题:为了获得文档的所有字段,必须多次连接表,代码本身必须多次迭代来构建查询(但这不应该是问题)

顺便说一句,多表是最常用的方法。。所以肯定有很多缺点

我在想,使用一张桌子会有什么好处:

| id | title | total_price | date | ec...
我用5个和50个附加字段做了一些测试;单表方法和多表方法之间的性能是惊人的:单表的速度大约快50倍

每次添加字段时,都会向表中添加一列。。这种方法会产生什么样的问题

编辑 让我提供一些细节:

  • 该应用程序仍处于设计阶段,是对字段编号为静态的旧应用程序的完全重新设计
  • 我们使用单表方法和多表方法(使用50个字段)对要存储的对象进行了一些模拟测试,结果如下:
  • 时间(秒):

    Test                                                            1°          2°          3°          4°          5°          avg
    1000 insert single_table                                        8,5687      8,6832      8,7143      8,7977      8,6906      8,69090137389466
    1000 select single table LIKE '%key%' on char(250) field        1,5539      1,5540      1,5591      1,5602      1,5564      1,556705142
    1000 select single table LIKE '%key%' on char(25) field         0,8848      0,8923      0,8894      0,8919      0,8888      0,889427996
    1000 select single table id = $n                                0,2645      0,2620      0,2645      0,2632      0,2636      0,263564462
    1000 select single table integer field < $j                     0,8627      0,8759      0,8673      0,8713      0,8767      0,870787334
    1000 insert multi_table                                         446,3830    445,2843    440,8151    436,6051    446,0302    443,023531816
    1000 select multi table LIKE '%key%' on char(250) field         1,7048      1,6822      1,6817      1,7041      1,6840      1,691367196
    1000 select multi table LIKE '%key%' on char(25) field          0,9391      0,9365      0,9382      0,9431      0,9408      0,939536426
    1000 select multi table id = $n                                 0,9336      0,9287      0,9349      0,9331      0,9428      0,93460784
    1000 select multi table integer field < $j                      2,3366      2,3260      2,3134      2,3342      2,3228      2,326600456
    
    测试1°2°3°4°5°平均值
    1000插入单_表85687 86832 87143 87977 86906 869090137389466
    1000在字符(250)字段15539 15540 15591 15602 15564 1556705142上选择单个表,如“%key%”
    1000在字符(25)字段08848 08923 08894 08919 08888 0889427996上选择单个表,如“%key%”
    1000选择单个表id=$n 02645 02620 02645 02632 02636 0263564462
    1000选择单表整数字段<$j 08627 08759 08673 08713 08767 0870787334
    1000插入多表4463830 4452843 4408151 4366051 4460302 443023531816
    1000在字符(250)字段17048 16822 16817 17041 16840 1691367196上选择多表,如“%key%”
    1000在字符(25)字段09391 09365 09382 09431 09408 0939536426上选择多表,如“%key%”
    1000选择多表id=$n 09336 09287 09349 09331 09428 093460784
    1000选择多表整数字段<$j 23366 23260 23134 23342 23228 2326600456
    
    第一种解决方案是“值属性”数据库:

    我会选择后面的解决方案:数据库是用来存储数据而不是结构的!我们遇到了一个大问题,因为我们有一个实体-值-属性数据库,我们可以插入任何类型的数据,但如果没有神奇的字符串,就不可能查询它们或针对特定的数据

    或者,您可以使用另一种解决方案:将additionnal字段存储在AdditionnalFields对象的序列化版本中。

    这个问题没有一个“正确”的答案。正如您已经提到的,它归结为灵活性和速度之间的权衡

    这取决于应用程序中的瓶颈是什么。你对你的应用程序做了一些分析吗?数据库查询时间是否与典型的最终用户ping时间、传输速度等相关?在您确定确实存在性能问题并知道瓶颈在哪里之前,担心优化性能是毫无意义的

    我喜欢使用Firefox上的firebug来计算我的页面与最终用户显示所需的时间,并将其与查询前启动、查询后停止的秒表计时器的结果进行比较。为了便于使用,我在评测期间将其打印在每页的底部

    您是否考虑过视图来弥补多表方法的缺点

    关于复杂的查询问题:使用“虚拟”视图,您可以避免在每天的查询中使用复杂的连接。将连接放置在视图定义中,更改动态字段时,只需调整视图即可。(注意:对于虚拟视图,使用视图定义中的联接动态重写“简单”查询。)

    关于速度问题:您可以使用“物化”视图定义和多表方法来获得单表性能。对于物化视图,DBMS通过使用视图定义中的联接,使用视图定义创建物理表。结果是您真正查询的是一个“单表”——但它会自动与多表定义保持同步。您以牺牲DB存储空间为代价,实现了两全其美

    根据您的DBMS,您还可以直接更新视图(而不是多表)。我相信MySQL就是这样。对于Postgres,您需要使用触发器来告诉系统如何修改底层多表

    CREATE TABLE [dbo].[ParentTbl]( [Id] [int] IDENTITY(1,1) NOT NULL, [KnownCol1] [real] NOT NULL, -- Lots of other columns ommitted [KnownColn] [real] NULL ) CREATE TABLE [dbo].[MainTbl]( [Id] [int] IDENTITY(1,1) NOT NULL, [ParentId] [int] NOT NULL, -- FK to ParentTbl.Id [KnownCol1] [real] NOT NULL, -- Lots of other columns ommitted [KnownColn] [real] NULL ) CREATE TABLE [dbo].[MainTblAttr]( [Id] [bigint] IDENTITY(1,1) NOT NULL, -- Note big int to cater for LOTS of records [MainId] [int] NOT NULL, --FK to MainTbl.Id [AttributeColumn] [nvarchar](255) NOT NULL, [AttributeValue] [nvarchar](max) NOT NULL )