我有一个表歌曲,其中包含标题和作者列。
作者可能创作了多首歌曲,因此本表中会重复一些信息。
这个问题可以通过创建另一个表 authors (id,author)并在歌曲表中创建对authors_id的引用来快速解决,这样我就可以节省内存数据库,但我的应用程序实际上是一个搜索引擎,它将对歌曲表执行大量查询,例如,如果它返回10个不同作者的结果它将需要在 authors 表上执行另外10个查询,以根据引用的ID找出作者姓名,这是不好的,因为搜索引擎必须立即返回结果。
现在,如果我删除了 authors 表,我只是将作者姓名直接放在歌曲表中,我就不需要对其他查询进行处理,但是歌曲表格会更大,需要更多内存,因此返回时间也会增加。
你会如何处理这种情况?
PS:这只是一个类似于我的问题的简单地图,实际上我的应用程序和数据库要复杂得多,所以我不能在这里给出全部内容。
答案 0 :(得分:2)
答案 1 :(得分:2)
将作者姓名放在歌曲表中不是一种非规范化形式,并且创建新的作者表不是规范化。我的假设是歌曲决定作者或歌曲决定多位作者。在这种情况下,歌曲表中的一个键是作者姓名的决定因素,所以尊重Boyce Codd Normal Form或Fifth Normal Form,歌曲表将是一个完全适合放置作者姓名的地方。
根据这里没有非规范化问题的理解,其他考虑因素仍然适用。在不知道如何在存储和索引中实现表的情况下,有太多变量可以对性能进行假设。
答案 2 :(得分:0)
如果您理解非规范化(您看起来如此)的权衡,并且它们适合您的应用程序和设计,那么请使用非规范化表。
事实上,对于读取,非规范化表通常比标准化表执行得更好,这仅仅是因为数据库没有额外的连接来计算。
当然,您应该测试两种解决方案的性能,看看哪种解决方案更适合您的应用。
答案 3 :(得分:0)
你总是要在性能和空间之间找到妥协。如果您真的想100%防止信息重复,那么您实际上只会有大多数表只有两列。请参阅http://en.wikipedia.org/wiki/Database_normalization。
但不要过度优化。始终首先编写哑法解决方案,测试性能并进行优化。程序员很难猜测瓶颈。只优化需要优化的内容。
答案 4 :(得分:0)
需要对性能进行测试:
记录数量将是重要因素,但最终通话是你的!
您还可以仅为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: