通过重复信息或遵守规则来打破规则?

时间:2011-01-30 21:48:26

标签: mysql database-design

我有一个表歌曲,其中包含标题作者列。

作者可能创作了多首歌曲,因此本表中会重复一些信息。

这个问题可以通过创建另一个表 authors (id,author)并在歌曲表中创建对authors_id的引用来快速解决,这样我就可以节省内存数据库,但我的应用程序实际上是一个搜索引擎,它将对歌曲表执行大量查询,例如,如果它返回10个不同作者的结果它将需要在 authors 表上执行另外10个查询,以根据引用的ID找出作者姓名,这是不好的,因为搜索引擎必须立即返回结果。

现在,如果我删除了 authors 表,我只是将作者姓名直接放在歌曲表中,我就不需要对其他查询进行处理,但是歌曲表格会更大,需要更多内存,因此返回时间也会增加。

你会如何处理这种情况?

PS:这只是一个类似于我的问题的简单地图,实际上我的应用程序和数据库要复杂得多,所以我不能在这里给出全部内容。

9 个答案:

答案 0 :(得分:2)

如果songs表存储了author_id,那么使用join通过一个查询返回所需的所有信息都是微不足道的。

如果您使用主键并正确加入,您的搜索结果将立即返回。

MySQL Joins

答案 1 :(得分:2)

将作者姓名放在歌曲表中不是一种非规范化形式,并且创建新的作者表不是规范化。我的假设是歌曲决定作者或歌曲决定多位作者。在这种情况下,歌曲表中的一个键是作者姓名的决定因素,所以尊重Boyce Codd Normal Form或Fifth Normal Form,歌曲表将是一个完全适合放置作者姓名的地方。

根据这里没有非规范化问题的理解,其他考虑因素仍然适用。在不知道如何在存储和索引中实现表的情况下,有太多变量可以对性能进行假设。

答案 2 :(得分:0)

如果您理解非规范化(您看起来如此)的权衡,并且它们适合您的应用程序和设计,那么请使用非规范化表。

事实上,对于读取,非规范化表通常比标准化表执行得更好,这仅仅是因为数据库没有额外的连接来计算。

当然,您应该测试两种解决方案的性能,看看哪种解决方案更适合您的应用。

答案 3 :(得分:0)

你总是要在性能和空间之间找到妥协。如果您真的想100%防止信息重复,那么您实际上只会有大多数表只有两列。请参阅http://en.wikipedia.org/wiki/Database_normalization

但不要过度优化。始终首先编写哑法解决方案,测试性能并进行优化。程序员很难猜测瓶颈。只优化需要优化的内容。

答案 4 :(得分:0)

需要对性能进行测试:

  • 如何在合并表时搜索(JOIN)
  • 如果autors名称在歌曲表中并且如果它增加了该解决方案(和索引)所需的空间,那么性能改进是什么

记录数量将是重要因素,但最终通话是你的!

您还可以仅为searchnig创建第三个表格(有关歌曲的有限信息以及歌曲的autor和idex),通过触发器调整歌曲并测试它是否可以提升性能

答案 5 :(得分:0)

如果用户要求给定作者的歌曲列表怎么办?然后你的搜索引擎必须搜索整个搜索表中的所有作者姓名字符串,这将是不好的。如果一首歌有多个作者怎么办?

如果您需要为查询提供大量连接,可以考虑规范化,但如果您不忘记使用索引作为键,则单个连接仍然非常快。

答案 6 :(得分:0)

对于实时数据库,您应该采取任何可行措施以避免不规范化数据。我绝对会创建一个Author表并在AuthorId表中添加Song列(标准表命名练习是使用单词的单数形式 - 你命名一行,基本上 - 不是复数.IE Song,而不是Songs,仅供参考。

通过加入Author表而不是在Song表中复制作者信息,您几乎肯定不会看到性能损失。

根据经验,您需要认真理由避免规范化,而不是这样做。

答案 7 :(得分:0)

测试结果..

对于此表

CREATE TABLE IF NOT EXISTS `song` (
`id` int(7) NOT NULL AUTO_INCREMENT,
`title` char(100) NOT NULL,
`author` char(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `author` (`author`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
song    Browse  Structure   Search  Insert  Empty   Drop    100,019     MyISAM  latin1_swedish_ci   25.8 MiB

选择标题为0.04s,作者来自歌曲WHERE title ='abf10924a290073ac1522aab6cd604d0'; 0.00004s for SELECT title,author FROM song WHERE author ='abf10924a290073ac1522aab6cd604d0'; (这是因为作者字段已编入索引)

对于这些表:

CREATE TABLE IF NOT EXISTS `author` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`author` char(100) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `author` (`author`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


CREATE TABLE IF NOT EXISTS `song` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`title` char(100) NOT NULL,
`authorid` int(5) NOT NULL,
PRIMARY KEY (`id`),
KEY `authorid` (`authorid`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

author  Browse  Structure   Search  Insert  Empty   Drop    10,000  InnoDB  latin1_swedish_ci   4.0 MiB     -
song    Browse  Structure   Search  Insert  Empty   Drop    ~90,129     InnoDB  latin1_swedish_ci   15.0 MiB    -

0.3s for SELECT t1.title,t2.author FROM song t1 JOIN author t2 ON t1.authorid = t2.id WHERE t1.title ='abf10924a290073ac1522aab6cd604d0';

我也使用InnoDB引擎的外键,结果是灾难性的,同一查询的结果为3秒。

结论,在这种情况下,非规范化表几乎比规范化表快十倍。 在这两种情况下,表格歌曲包含大约100,000行md5哈希值。

我正在等待您的意见,也许我没有正确使用JOIN,并且在第二种情况下表格没有被有效编入索引。

答案 8 :(得分:0)

从我的pov:

  • 如果您的数据库仅用于查询目的,则单行将为您提供查询所需的所有答案 - >没有规范化
  • 您的数据库是否会更新?使用标准化来提供一致性并减少混乱。