Mysql

數據抓取/倉庫應用程序的數據庫設計建議?

  • September 2, 2014

我正在研究數據倉庫類項目的數據庫設計,該項目每天涉及大量插入。數據檔案將進一步用於生成報告。我將有一個使用者列表(例如一個 200 萬的使用者集),我需要為此監控與他們相關的日常社交網路活動。

例如,假設有一組 100 個使用者說 U1、U2、…、U100。

我需要將他們的每日狀態計數插入我的數據庫。

考慮從 6 月 30 日到 7 月 6 日期間為使用者 U1 獲得的總狀態計數,如下所示

June 30 - 99
July 1 - 100
July 2 - 102
July 3 - 102
July 4 - 105
July 5 - 105
July 6 - 107

數據庫應保留每個使用者的每日狀態計數,例如使用者 U1:

July 1- 1 (100-99)
July 2- 2 (102-100) 
July 3- 0 (102-102) 
July 4- 3 (105-102) 
July 5- 0 (105-105) 
July 6- 2 (107-105) 

同樣,數據庫應該保存完整使用者集的每日詳細資訊。

在稍後的階段,我設想從這些數據中提取匯總報告,例如每天、每週、每月等的總分;並將其與舊數據進行比較。

我需要從頭開始。我對 PHP 作為伺服器端腳本和 MySQL 很有經驗。我在數據庫方面感到困惑。由於我每天需要處理大約一百萬個插入,所以應該注意哪些事情?

我對如何在這方面設計 MySQL 數據庫感到困惑。要使用哪種儲存引擎以及應遵循哪種設計模式,請記住數據可以在以後有效地與聚合函式一起使用?

目前,我設想 DB 設計使用一個表來儲存所有使用者 ID,並使用外鍵和每天的單獨狀態計數表。

MySQL 是否符合我的要求?每天完成 200 萬次或更多的數據庫操作。在這種情況下如何考慮伺服器和其他事情?

編輯:

涉及的查詢:

插入查詢

插入查詢應該能夠每天插入 1-2 百萬個插入。(我們這裡沒有更新。)

檢索查詢

1.整個使用者集的狀態總和。

2.在一個地理​​位置下的一組使用者的狀態總和。

3.將狀態計數與天/週/月進行比較。

–>我相信在這種情況下需要某種索引,但我讀過索引可能會減慢插入速度。

–>另外我聽說考慮到速度方面,MyISAM 會比 InnoDB 更好。

請指教?

這些是一般性建議,因為您沒有顯示要執行的查詢的全部範圍(您計劃執行哪種分析)。

假設您不需要實時結果,您應該在期末對數據進行非規範化,在所有必要的時間範圍內(按天、按週、按月)預先計算匯總結果,並且只使用匯總表。根據您打算執行的查詢,您甚至可能不需要原始數據。

如果持久性不是問題(您總是可以重新計算統計資訊,因為原始數據在別處),您可以使用記憶體機制(外部,或 MySQL 5.6 包含 memcache),它非常適合在記憶體上寫入和讀取鍵值數據。

使用分區(也可以手動完成),與這類應用程序一樣,通常最常訪問的行也是最近的。刪除舊行或將舊行存檔到其他表以有效地使用我們的記憶體。

如果您想要持久性、高並發寫入並且您最常訪問的數據將適合記憶體,請使用 Innodb。還有 TokuDB——它可能不是原始速度更快,但在處理巨大、高大的表上的插入時它可以更好地擴展,並允許在磁碟上進行壓縮。還有像Infobright這樣的以分析為中心的引擎。

編輯:

在任何具有壞磁碟的儲存中,每秒 23 次插入都是可行的,但是:

  • 您不想使用 MyISAM - 它不能進行並發寫入(除非在非常特定的條件下),並且您不希望有巨大的表損壞並失去數據
  • 預設情況下,InnoDB 是完全持久的,為了獲得更好的性能,您可能希望降低持久性或擁有良好的後端(磁碟記憶體)。InnoDB 在插入大表時往往會變慢。巨大的定義是“主鍵/其他唯一索引的上部必須適合緩衝池”以檢查唯一性。這可能因可用記憶體而異。如果您想要超出此範圍的可擴展性,則必須分區(如我上面建議的)/分片或使用我之前提到的任何替代引擎(TokuDB)。

SUM()統計資訊不能在普通 MySQL 引擎上擴展。索引再次提高了性能,因為大多數操作都可以在記憶體中完成,但是仍然必須在單個執行緒中讀取每一行的一個條目。我提到了設計替代方案(匯總表、記憶體)和替代引擎(基於列)作為解決方案。但是,如果您不需要實時結果,而是需要類似報告的查詢,則不必太擔心。

我建議您使用假數據進行快速負載測試。我有很多客戶對社交網路的 MySQL 進行分析而沒有問題(至少,在我幫助他們之後 :-)),但您的決定可能取決於您實際的非功能性需求。

除了 Jynus 所說的:確保您的表Date首先在物理上集群。這將使范圍掃描非常有效,因此長達數週或數月的聚合將很快。即使您選擇在匯總表中實例化這些週或月級別的總計,按日期進行分群也會有助於快速更新。

這種情況 - 許多範圍掃描 - 是一個很好的例子,說明您選擇低基數欄位而不是高基數欄位(使用者 ID)。但是,您仍然需要對 的索引UserID

CREATE TABLE Activity
(
Date        DATE NOT NULL,
UserID      INT NOT NULL REFERENCES Users(UserID),
PRIMARY KEY (Date, UserID),
NumUpdates  TINYINT UNSIGNED  -- Assuming that a user cannot update more than 255 times per day; alternately, consider SMALLINT
)

引用自:https://dba.stackexchange.com/questions/72709