[英]Database Design for large datasets
我目前正在設計一個數據庫表,其中我們將有幾億條記錄,我想知道管理它的最佳方式是什么。 對於這些類型的數據集,我們最終會遇到維護問題,例如表還原或更改表需要很長時間。 現在我對如何處理這個問題有了一些想法,但也許有更好的方法?
由於我們的數據越新就越相關,我們可以將其拆分為短時間范圍(例如過去 30 天)和舊數據集(比過去 30 天舊)。 為此,我看到了兩種可能性:
將其拆分為兩個分區,當前分區和舊數據分區
好處:
缺點:
手動將其拆分為兩個表並通過夜間作業移動數據。 在上面我們放了一個視圖來選擇數據
好處:
缺點:
所以我的問題是,在這種情況下,最佳實踐是什么? 你會建議做什么?
謝謝
幾億是很多,但對於今天來說並不是一個大數據集。 大型數據集有數十億條記錄。 這里的問題是我認為,您的數據增長速度有多快? 你對它運行什么類型的查詢? 如果您的數據增長非常緩慢,那么即使沒有分區,任何數據庫軟件都可以足夠快地處理該數量。 如果它增長很快,最好進行一些分區。
如果您有 OLTP 工作負載,那么小的查詢具有高延遲但數量很多,最好將熱數據保存在單獨的位置。 如果它們取決於時間,我建議您使用基於日期時間列的本地分區,按年份分區。 這樣,大多數基於最近數據的查詢只會檢查最新的分區,並且可能只檢查整個數據集的很小一部分。
如果最近意味着很短的時間,比如 1 個月,那么上述方法雖然仍然有用,但還是不夠。 因此,您可以在其上創建另一個熱數據表。 現在您有一個按年份分區的大數據表(始終包含所有數據)和一個包含最近數據的小表。 為了克服缺點,你可以這樣做:
或者您可以將相關查詢發送到兩個表並確保它們在應用程序級別(應用程序級別邏輯)上保持一致。 這個可能會更高效,因為 mysql 觸發器可以更多地減慢數據庫的速度。
SELECT 查詢將根據查詢轉到新表,否則轉到主表(按年份分區有助於提高性能)。 如果您想要靈活,也可以使用代理來完成查詢拆分。 Proxysql可以輕松處理。 它還有其他好處,例如緩存和連接多路復用。
要丟棄熱數據表中的舊數據,您可以每天執行一個事件以刪除超過 1 個月的記錄。 如果您有成千上萬的要刪除,則應將它們分成較小的塊刪除,以防止出現鎖定、滯后和大量資源消耗等問題。 另一種方法是使用is_deleted列來識別過時的記錄,並以此進行分區。 隨時刪除分區是即時的。
對於非阻塞 DDL 操作,有一些開源工具可以在線遷移您的架構,而不會降低很多性能。 查看pt-schema-change和ghost 。
(專注於舊數據與新數據)
如果表按時間順序排序並且您主要訪問“新”數據,那么大量緩存和它提供的性能將自動內置。
只要確保使用 InnoDB 並讓PRIMARY KEY
為AUTO_INCREMENT
(或以DATETIME
開頭)。
讓我們運行一些數字。 如果表中有 300M 行,每行占用 100 個字節(一個簡單的經驗法則),那么表的數據占用 30GB。 索引和其他表會有更多。 如果您在具有 64GB RAM 的服務器上運行(今天並非不合理),那么所有內容都可能適合 RAM 並且不需要太多 I/O。
相反,如果您只有 8GB 的 RAM 並且大部分活動都在表的最新 10% 中,那么同樣,它將被很好地緩存。
(注意:I/O 是性能的最大硬件組件。)
通常會阻礙大型表設計的是索引、查詢公式,甚至是整體架構。 但是,由於您沒有關於此類的詳細信息,因此我跳過了該內容。
您提到了一種粗略的手動分區表的方法。 有一些內置的東西: PARTITIONing
。 但它不太可能幫助插入、更新或選擇,所以我不推薦它而不做進一步討論。
如果您最終會清除“舊”數據(比如一年后),那么PARTITIONing
是一個好主意。 如果表只保存 1 年的數據,我將使用每周分區。 如果您需要,我們可以進一步討論。 但請注意,唯一的好處是通過DROP PARTITION
刪除舊數據; 分區是。
SUBPARTITIONs
沒有任何幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.