我想知道,把一个表分成三个表,每个表大约有6列,使用外键,还是使用一个表,并且有15列呢?
大部分的字段都是varchars,这里和那里都有一些数字。数据库是MySQL。
更好的是,我最感兴趣的是插入和选择速度。
为了澄清这一点,这是一个一对一的具体表格,数据大多是用户数据,属性将是位置、年龄、活动性别等,因为只涉及一个用户。是的,我试图把热柱和冷柱隔离开来。
发布于 2017-04-07 05:33:39
我建议对三种有限的情况进行垂直分区:
TEXT (在BLOB中)。即便如此,这也是值得怀疑的,因为InnoDB会自动执行类似的操作。NULL,而是对辅助表使用一个LEFT JOIN,并在缺少数据时省略行。这是否比伤害更有帮助是值得怀疑的。进入垂直分区的一种意外方法是,当您需要为一个包含很多行的表添加一些新列时,但是无法承担添加这些列的停机时间。相反,创建一个并行表来保存新列。但是请注意,ALTER TABLE .. ALGORITHM=IMPLACE基本上消除了对此技术的需求。
40栏开始太多,400栏太多了。也就是说,15本身并不是一个问题。
至于性能方面,是的,正如其他答案所述,在这两个方向上都会出现一些性能问题。
如果你不是在谈论数以百万计的行,别担心。
我的经验法则之一是:如果我不能期望得到10%的改进,那么花点时间在其他地方进行优化。
底线:做对你最有效的事情;以后再担心优化。
发布于 2017-04-06 17:43:45
如果这些表具有一对一的关系(表1中的每一行将绑定到表2中的一行,以及表3中的一行),那么INSERT和SELECT语句可能会慢一些(要插入的数据量相同,加上外键,以及插入时可能需要更新的附加索引;在选择时,您将获得将表连接在一起的额外开销)。
然而,在大多数情况下,在讨论这类事情时,Table2和Table3中的每一行都将绑定到表1中的多个行(或者,Table3将绑定到Table2中的多个行,而不是表1)。例如,如果您有一个employee表,其中包含division、division_address、division_city、division_state和division_zip字段,则可以将这些字段移动到division表;而且,想必每个员工都会绑定到一个部门,每个部门可能有许多员工。
在这种情况下,INSERT可能更快(您可能在索引结构上有差异,但在大多数情况下您将在每一行中插入6列,而不是15列),而SELECT可能会更慢(必须将表连接在一起以获得所有数据需要额外的工作;然而,在某些情况下,如果Table2或Table3上的索引提供了更快的方法来缩小需要检查的行总数;即使在最坏的情况下,我们也应该减少处理查询所需读取的数据量)。
但是,不要忽视正常化的其他好处。只输入一次division信息(使用上面的例子),我们避免输入导致每个部门在employee表中有7个不同名称的输入。我们使更新部门名称或地址变得更简单(并且避免在发生这种情况时锁定employee表)。而且,我们(在大多数情况下)在数据库中存储的冗余数据要少得多,这也节省了我们的空间。
然而,对你的问题最好的答案可能是“试一试”。我们不知道您的数据,或者查询速度的差异(例如2%)在您的环境中是否至关重要。
通常,我建议从一个更规范化的数据库开始(同样,就我的例子来说,拆分employee和division),并且只有在性能不能接受的情况下才进行去角色化(将division放回employee),并且测试表明合并这两个表将使性能恢复到可接受的标准。这是因为,要将为每个员工输入的部门数据准确地组合到实际的部门结构(由于上述类型的类型),要比复制规范化的division数据并复制到绑定到它的每个employee行要困难得多。
发布于 2017-04-06 20:23:17
这是一种常见的去标模式,称为“垂直分区”。
当大多数查询只覆盖表中的一小部分列时,这可能很有用。如果不需要的列很大(例如blobs)。
通过“折叠”较少使用的列,您可以适应更多的每页行。更多的藏在不同的地方。
另外,假设较少使用的数据将受益于压缩,而热数据则不会。现在你把它放在另一个桌子上,你可以压缩它而不损害另一个。
这样做的代价是插入和删除速度较慢,因为必须进行额外的查询、引用完整性检查、获取额外的锁、维护外键的冗余索引。
键列上的更新将更加昂贵,因为必须级联到其他行及其索引。
跨多个表的读取将不得不连接,因此将花费更长的时间。
将使用更多的磁盘空间作为每个表的键列的存储和索引。
数据库现在变得更加复杂和难以维护。
与几乎所有的优化一样,除非需要,否则不要这样做。
https://dba.stackexchange.com/questions/169336
复制相似问题