日益增長的數據庫之痛
祝大家新年快樂。我希望在以下情況下獲得一些一般性指導……
我有一個已經執行了大約 10 年的應用程序。數據儲存在 mysql 中(現在在 AWS Aurora 上)。
一些處於一對多關係的表開始有更多的行:
Records (~1.4million rows) | V (1 to many) | V SubRecords (~10million rows) | V (1 to many) | V SubSubRecords (~22million rows)
這些行中儲存的實際數據並不多(即 subSubRecords 總共大約 5gb),而且我執行的查詢非常簡單,使用沒有連接的索引鍵。例如…
SELECT ... FROM Records WHERE id = ?; SELECT ... FROM SubRecords WHERE recordId = ?; SELECT ... FROM SubSubRecords WHERE subRecordId = ?;
到目前為止,一切都繼續保持高性能。
但是,我開始擔心這種設計會隨著時間的推移而保持不變。雖然在 SubSubRecords 中達到 2200 萬行需要 10 年,但現在數據庫的增長速度要快得多。看到該表在接下來的 5 年內攀升至 1 億行,我不會感到驚訝,這感覺很多。而且我不確定它會在什麼時候成為問題。
我意識到這是一個相當廣泛的問題,並且取決於情況。但在這些情況下,一般推薦哪些類型的解決方案?
- 設置分區?(這些表使用外鍵來強製完整性,我的理解是這與分區不兼容。)
- 將 subRecords 和 subSubRecords 中的數據轉換為 json 有效負載並將其直接儲存在主記錄表的 json 列中?(如果重要的話,數據量相同,但行數更少。)
- 移動到一個完全不同的數據庫?(Mongo?我對此一無所知,但聽說在某些情況下更擅長縮放。)
- 忽略它直到它成為一個問題?:D
歡迎那些遇到過類似問題的人提出任何建議/智慧的珍珠。在此先感謝您的幫助!
附錄:
根據要求,這是上述表格的 CREATE TABLE 語法…
CREATE TABLE records ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, typeId TINYINT(1) UNSIGNED NOT NULL, userId INT UNSIGNED NOT NULL, updated TIMESTAMP DEFAULT NOW() NOT NULL, savename VARCHAR(100) NOT NULL, title VARCHAR(100) NOT NULL, instructions TEXT NOT NULL, FULLTEXT ftRecords(savename, title), PRIMARY KEY(id), FOREIGN KEY(typeId) REFERENCES recordTypes(id), FOREIGN KEY(userId) REFERENCES users(id) ON DELETE CASCADE ) ENGINE=InnoDB CHARACTER SET=utf8; CREATE TABLE subRecords ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, recordId INT UNSIGNED NOT NULL, thumbnailId INT UNSIGNED NULL, sortOrder SMALLINT NOT NULL, enabled TINYINT(1) DEFAULT 0 NOT NULL, title VARCHAR(100) NOT NULL, instructions TEXT NOT NULL, parameters VARCHAR(500) NOT NULL, PRIMARY KEY(id), FOREIGN KEY(recordId) REFERENCES records(id) ON DELETE CASCADE, FOREIGN KEY(thumbnailId) REFERENCES thumbnails(id) ON DELETE SET NULL ) ENGINE=InnoDB CHARACTER SET=utf8; CREATE TABLE subSubRecords ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, subRecordId INT UNSIGNED NOT NULL, thumbnailId INT UNSIGNED NULL, sortOrder SMALLINT NOT NULL, caption VARCHAR(200) NOT NULL, PRIMARY KEY(id), FOREIGN KEY(subRecordId) REFERENCES subRecords(id) ON DELETE CASCADE, FOREIGN KEY(thumbnailId) REFERENCES thumbnails(id) ON DELETE SET NULL ) ENGINE=InnoDB CHARACTER SET=utf8;
100M 行並不可怕。
分區——不。它不太可能增加任何性能優勢。但是,如果您需要清除“舊”數據,則可能需要進行分區。
如果
recordId
是INDEX
——SubRecords
好。如果
recordId
是–的第一列就PRIMARY KEY
更好SubRecords
了。向我們展示
SHOW CREATE TABLE
進一步的建議。如果您將 3 個表放在一個 3 中,您的3
SELECTs
會執行得更快。JOINed``SELECT
分群
一個輕微的改進是改進您同時獲取的行的“集群”。對於
SubRecords
,ALTER TABLE SubRecords DROP PRIMARY KEY(id), ADD PRIMARY KEY(recordId, id), ADD INDEX(id);
這樣,當您獲得一條記錄的多個子記錄時,它們將彼此相鄰。這是因為
PRIMARY KEY
(在 InnoDB 中)與數據“聚集”在一起。是INDEX(id)
為了保持AUTO_INCREMENT
快樂。在數據集大於 RAM 之前,此更改可能不會顯示任何明顯的改進。
類似的事情可以用
SubSubRecords
.