2010-10-03 67 views
3

我有一个网站,人们可以添加他们最喜欢的电视剧。有一个功能可以检查你看过的剧集。数据库表获得太多的数据 - 需要另一种解决方案

每个被选中的剧集都会在数据库表(使用user_id,show_id和episode_id)中创建一条记录。
此表现在超过600.000行,增长速度非常快!

我设置了索引,但是我觉得在查询这个表格时性能越来越差。

我的新的解决方案的想法:

所以不是:

user_id | show_id | episode_id 
1 ....... 123 ......7675 
1 ....... 123 ......7676 
1 ....... 123 ......7677 
1 ....... 456 ......5678 
1 ....... 456 ......5679 
1 ....... 456 ......5680 

我可以这样做:

user_id | show_id | episode_ids 
1 ....... 123 ......7675,7676,7677 
1 ....... 456 ......5678,5679,5680 

那我就必须将字符串分割成一个数组,并使用array.include?(some-id)
这应该可以缓解数据库,但是Ruby会处理更多的数组代码。

我在正确的轨道上吗?或者有人可以想出更好的解决方案吗?

+2

我会亲自坚持第一个例子,但我不是专家,所以我会离开它的人更多线索回答。 – chigley 2010-10-03 13:14:45

+0

'show_id'可以从'episode_id'派生吗? – 2010-10-03 13:23:55

回答

13

否否否,这绝对不是构建这样的数据库的方式。 varchar字段中的逗号分隔列表是您应该考虑的最不可取的反模式。

这听起来对我来说就像你的表现问题是基于猜测。因此,而不是:

  • 确定是否真的有问题
  • 在非生产环境中使用适当的仪器
  • 测试可能的解决办法找到它的原因。

600k行是没有(在一个表中有三个整数)。真。即使是最小的服务器,这也可以适用于公羊。从ram中查询表格应该非常快,你不用担心。

如果您经过第1步(确实存在问题),请提出更多问题,其中包含您的整个相关模式,确切查询,解释计划和计时数据。

+0

谢谢:)我想我必须进一步调查。 – Frexuz 2010-10-03 16:52:13

1

以下是我想结构表:

USERS 
userid INTEGER PRIMARY KEY 
username text/varchar/whatever 

SHOWS 
showid INTEGER PK 
showname varchar or nvarchar or text [depending on what database I was using] 
etc etc 


EPISODES 
episodeid INTEGER PK 
showid INTEGER FK references SHOWS [index this field] 
ordinal DECIMAL [indicates which episode -- DECIMAL makes it easier to insert later an episode you overlooked] 
episodename text/varchar/nvarchar whatever 
etc etc 

SEENIT 
id INTEGER AUTOINCREMENT PK 
userid INTEGER foreign key ref USERS 
episodeid INTEGER foreign key ref EPISODES 

你可以放置(用户ID,episodeid)备用独特的复合指数或使用单独的索引,一个在用户ID,一个在episodeid。我可能会用后者去。

2

您是否将数据非规范化是一个有争议的问题。它可以在特定情况下有其优点,但从关系的角度来看,它可能不应该是你的第一选择。相反,解决这个问题的首选步骤应该是分析它并实施不改变数据结构但主要处理数据库系统及其环境的解决方案。因此:

  • 问题的来源真的是数据库吗?还是它是一些其他系统(网络,网络服务器,铁轨等)?
  • 在查询响应时间方面什么是可以接受的?在所有情况下查找数据库应遵守的具体数字。
  • 哪些查询变慢?也许你有慢速,低效率的查询可以重构。制定一个查询计划,看看优化器在做什么。
  • 您是否正确使用索引?
  • 调整你的mysql实例。您可以通过调整实现很多。
  • 见,你可以在硬件方面做一些事情(获得更多的内存,更快的磁盘等)
  • 创建视图的顶部,最常用的查询,如果有任何
  • 如果上述所有完成后,你仍然可以做分片。这在应用程序之上增加了一些复杂性,但它可以让您在不需要太多努力的情况下在很大程度上扩展您的系统。
  • 最终,您可能会得出结论:您必须使用“真正可扩展的”分布式键/值存储(nosql)。但在60万行之前,要走到这一步还有很长的路要走。

这就是说 - 如果您发现您提出的解决方案是提高性能的最佳方法,请继续并反规范化。关键是你应该意识到所有的选择,并选择最好的与具体的性能相关的目标。

0

我会坚持规范化的数据。这听起来更像是一个查询优化问题。请记住,mysql(假设你正在使用它)每个查询只使用一个索引,你可能会通过设置一个复合索引获得更好的性能。 也可以使用mysql查询浏览器中的EXPLAIN语句。更多的信息在这里: http://dev.mysql.com/doc/refman/5.1/en/explain.html

+0

从MySQL 5.0开始,每个查询可以使用多个索引,使用索引合并可以找到最终结果。请参阅:http://dev.mysql.com/doc/refman/5.1/en/index-merge-optimization.html – Martin 2010-10-03 17:09:53

+0

我的不好,完全忘了这一点。它实际上表现如同一个声明的复合索引吗? – 2010-10-03 20:13:53

相关问题