2010-10-03 45 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

相關問題