我有一个网站,人们可以添加自己喜欢的电视剧。有一个功能可以检查你看过的剧集。
每个已检查的剧集在数据库表格中创建一条记录(使用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可以处理更多更重的数组代码。
我是否在正确的轨道上?或者有人能想到更好的解决方案吗?
答案 0 :(得分:13)
否否,这绝对不是构建这样一个数据库的方法。 varchar字段中以逗号分隔的列表是您应该考虑的最不理想的反模式。
这听起来像你的性能问题是基于猜测。所以相反:
600k行没有(在一个有三个整数的表中)。真。即使是最小的服务器,这也可以适用于ram。从ram中查询表应该是如此之快,你不必担心它。
如果您越过第1步(确实存在问题),请进一步询问包含整个相关模式,确切查询,解释计划和时间数据的问题。
答案 1 :(得分:2)
您是否对数据进行非规范化是一个有争议的问题。它可以在特定情况下有其优点,但从关系的角度来看,它可能不应该是你的首选。相反,解决此问题的首选步骤应该是分析它并实现不改变数据结构但主要处理数据库系统及其环境的解决方案。因此:
话虽如此 - 如果您发现您提出的解决方案是提高性能的最佳方法,请继续进行反规范化。关键是你应该了解所有选项并选择具有与性能相关的具体目标的最佳选项。
答案 2 :(得分: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
您可以在(userid,episodeid)上放置备用唯一复合索引,或者使用单独的索引,一个在userid上,一个在episodeid上。我可能会选择后者。
答案 3 :(得分:0)
我会坚持使用标准化数据。这听起来更像是一个查询优化问题。请记住,mysql(假设您正在使用它)每个查询只使用一个索引,并且您可以通过设置复合索引获得更好的性能。 还可以在mysql查询浏览器中使用EXPLAIN语句。更多信息: http://dev.mysql.com/doc/refman/5.1/en/explain.html