Str*_*rae 3 database-design design-patterns database-schema
我必须选择将使用动态字段存储内容类型(例如,博客文章,页面,文档,发票,估计等等)的数据库的结构:例如,Estimate内容类型应具有字段title,date和total price.
然而,在这些田地可以添加矿石去除的时间,所以1年后,Estimate含有类型的notes田地可以有.
这是由着名的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 |
Run Code Online (Sandbox Code Playgroud)
等等..
我的观点是这种方法非常灵活,但很容易陷入性能问题:为了获取文档的所有字段,您必须多次连接表,并且代码本身必须多次迭代才能构建查询(但这不应该是一个问题).
顺便说一句多表是最常用的方法..因此必须有很多缺点.
我在考虑使用单个表会有什么样的不利之处:
| id | title | total_price | date | ec...
Run Code Online (Sandbox Code Playgroud)
我做了一些测试,有5个和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
Run Code Online (Sandbox Code Playgroud)
可能值得研究NoSQL数据库的可能性.我自己并没有太多使用它们,但鉴于你说你需要"...存储内容类型(例如,博客文章,页面,文档,发票,估算等等)"和动态字段"看起来好像它可能是一种合理的方法.
来自维基百科的文章 ;
...这些数据存储可能不需要固定的表模式,通常避免连接操作,并且通常水平扩展.
和
通常,NoSQL数据库根据它们存储数据的方式进行分类,并且属于键值存储,BigTable实现,文档存储数据库和图形数据库等类别.
我不是说这是你所有问题的答案,但我肯定会说这值得一看.
关于其他方法,我过去曾使用实体 - 属性 - 值(EAV),虽然性能可能落后于固定架构,但我觉得这是一个必须提供灵活性的折衷方案.架构.
我的情况可能与你的情况有所不同,但如果有任何帮助,我会为你安排.我们将表结构打破成了符合我们情况的逻辑.有一个自然的层次结构,因为有一个父表,其他表的大部分都与之相关.
尽管由于我们正在处理的数据种类繁多,我们需要动态结构,但也有一些固定的结构.因此,对于需要动态结构的每个表,我们创建了一个"主"表和一个"属性"表.
下面是一个例子(SQL Server特定的);
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
)
Run Code Online (Sandbox Code Playgroud)
然后,您可以执行PIVOT查询以帮助您获取数据.鉴于您将拥有不同的属性,您需要确定要包含在枢轴中的列.我发现这个例子在我开发解决方案时非常宝贵.但是,SO上有很多例子.只需搜索数据透视动态列.
在我的实例中,拥有父表对于限制我需要遍历的数据量有很大帮助,因为它限制了我需要查看的子记录.在你的情况下可能不是这样,但希望这会给你一些想法.
祝你好运.