哪個數據庫系統可以讓我自由?
我目前正在執行一個 MySQL 數據庫來記錄和分析這些日誌。
我目前的表架構如下所示:
CREATE TABLE `mylogs` ( `transfer_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , `client_id` INT UNSIGNED NOT NULL , `client_ip` INT UNSIGNED NOT NULL , `server_1_ip` INT UNSIGNED NOT NULL , `server_2_ip` INT UNSIGNED NOT NULL , `service` ENUM( 'service1', 'service2', 'service3', '...', 'service500' ) NOT NULL , `mb_transferred` FLOAT UNSIGNED NOT NULL , `time` TIMESTAMP NOT NULL ) ENGINE = MYISAM ;
我執行一項服務,在其中提供大量下載,這些下載在目標主機和源主機之間超過 1 個額外的主機。它們由 32 位 IP 地址的整數解釋表示。
我的系統目前在高峰時段處理大約 500 次插入/秒。我執行一個主從系統。主伺服器有一個帶有 PHP 文件的 apache 網路伺服器,該文件從遠端主機呼叫,並在日誌表中插入一行。然後將更改複製到發生查詢的從屬伺服器。
我的查詢主要是在由 client_id 過濾的時間欄位中的某個範圍內對 mb_transferred 欄位進行聚合。
SELECT SUM(mb_transferred) FROM mylogs WHERE client_id = 123 AND time > '2012-01-01 00:00:00'
maser 伺服器執行一個帶有簡單 php 文件的 apache 網路伺服器,該文件執行插入並被其他伺服器呼叫。
我的伺服器現在快到極限了。我已經升級到大型硬體。
我考慮過使用 GUID 作為主鍵並使用主主複製,這肯定會減輕一些事情,但我認為它是短視的,因為它不會減少每台伺服器的插入量。
我預計未來會有更高的低谷,我也擔心數據庫的大小。
同樣在未來我計劃有第二個表來定義某些服務的“權重”。
就像是:
CREATE TABLE `mylogs`.`service_weight` ( `plan` TINYINT NOT NULL , `service_name` ENUM( 'service_1', 'service_2' ) NOT NULL , `weight` FLOAT NOT NULL , PRIMARY KEY ( `plan` , `service_name` ) ) ENGINE = MYISAM ;
然後我想對該表執行連接查詢,並將 mb_transferred 欄位與權重因子相乘。
我還想在日誌表中添加諸如“transfer_duration”之類的欄位,以計算下載速度並執行查詢以獲取統計數據,某些網路或某些主機的某些伺服器之間的連接有多好/多差。
重點是。資料結構很簡單,只有大量的行。
我有很多聚合函式。這使我大腦的“地圖縮小”部分的燈泡閃爍。
我 thugth 關於做垂直分片並使用 client_id 作為斷點。例如,如果我有 10 個伺服器將每個使用者發送到其使用者 ID mod 10 伺服器。這將很容易並減輕負擔。但是縮放可能會很尷尬。
因此,我認為,隨著目前的增長,我預計將很快達到項目的規模,除了轉向分佈式數據庫系統之外,我無能為力。
我已經嘗試檢查 cassandra、project voldemort、amazon dynamodb 和 hbase,但無論我讀了多少書,我似乎都在碰壁。
我認為多年的關係思維不知何故阻礙了我的思想。
有人可以指出我正確的方向嗎?什麼數據庫系統適合我的案例,為什麼?
- 我不需要絕對到第二個數據,複製延遲是可以接受的。
- 我不會有更新,只有插入。
- 我想要一個容錯系統
- 數據量越來越大,所以分片系統會很好
- 我的 I/O 負載很重
有很多要考慮的。我將把它縮小到一個問題並提供一個解決方案,儘管有很多方法。
問題:您需要對大量行進行 AD-HOC 查詢。
首先,設置一個伺服器來處理寫入和一個複制的從屬伺服器(執行某種 MySQL 5.5.x)來處理讀取。我個人的偏好是 Percona Server。你的旅費可能會改變。
複製完成後,將您的從表更改為:engine=InnoDB,ROW_FORMAT =COMPRESSED,按日期分區,並索引數據以優化您的查詢WHERE子句。其中每一個都針對您的情況進行了優化,並且需要進一步調整。
最後,設置一個計劃以在數據超出範圍時對數據進行歸檔/分片。說2-3年。取決於您的 SLA 是否提供回饋報告。如果需要,您可以隨時合併它。
MySQL 5.6 將內置 Memcached,允許您儲存預處理結果。Map/Reduce 很棒,只要它不是 reduce 函式的第一次執行。只要數據已經被處理,NoSQL 就很棒。也不是你的問題。
2012-06-13 補充:由於我的建議似乎引起了另一種反應,我將送出我的理由:
- 在這種情況下為什麼選擇 InnoDB?隨著許多行的不斷插入,您可以使用 InnoDB 來避免表級別的隱式讀鎖。
- 為什麼選擇壓縮 + 梭子魚?“壓縮意味著更少的數據在磁碟和記憶體之間傳輸,並且佔用更少的記憶體空間。具有二級索引的表的好處被放大了,因為索引數據也被壓縮了。”
- 為什麼要按日期分區?減小掃描寬度。
- 為什麼要正確索引?通過消除全表掃描來減少 CPU 瓶頸,從而減少搜尋時間。
我開始這只是對蘭迪的評論回复,但空間不足。
- Innodb 從屬端對我來說似乎很奇怪。您應該關注該引擎的主要原因是數據一致性和災難恢復。這意味著如果您必須選擇一個,您希望它在主人身上。此外,innodb 提供的行級鎖定將更好地使您能夠在寫入發生時潛在地避免表鎖阻塞主選擇。這當然取決於您的訪問模式。
- 我的壓縮行結果好壞參半。根據我的經驗,它們絕對可以節省諸如日誌記錄之類的空間,但顯然你正在受到 CPU 的影響。如果您在任何地方都受到資源限制,請仔細權衡和基準測試是 CPU 受限還是 I/O 更適合您。您說您的 I/O 很高,但我不確定還有什麼情況,如果這是專用伺服器等。如果您正在執行 percona,請查看 information_schema.INNODB_CMP 表以獲取有關所用時間的壓縮統計資訊做這些操作。如果您走那條路線以查看最適合您的方法,則在設置壓縮行時使用不同的 key_block 大小。此外,請確保您的 file_format 設置為 Barracuda。如果它設置為 antelope,alter 將成功,因為您的行並沒有真正壓縮,所以您只是浪費時間。
- 按日期分區對於日誌可能是明智的,因為您可能會按該維度進行查詢。請記住按範圍分區,該軸必須是主鍵的一部分。如果您要查詢的不僅僅是日期,您可能需要一個複合鍵。如果您正在這樣做並且 innodb 記住大型 PK 會迅速膨脹您的索引要求,因為每個二級索引都儲存了完整 PK 的副本。
- 如果您有二級索引,請記住按範圍分區實際上會損害您的性能,因為它現在必須掃描每個分區以查找匹配項,並且您失去了分區修剪的好處。
也許最重要的是:您可能正在重新發明輪子。已經有完全圍繞日誌收集和聚合分析的案例建構的開源項目,例如 Graylog。也許這些都不適合你的案例,但我認為如果他們這樣做的話,值得做更多的研究。