Mysql

數據庫重新設計機會:該感測器數據收集使用什麼表設計?

  • February 2, 2021

背景

我有一個由大約 2000 個感測器組成的網路,每個感測器都有大約 100 個數據點,我們每隔 10 分鐘收集一次。這些數據點通常是 int 值,但有些是字元串和浮點數。此數據應儲存 90 天,如果可能,應儲存更多天且仍然有效。

數據庫設計

最初負責這個項目時,我編寫了一個 C# 應用程序,為每個感測器編寫逗號分隔的文件。當時沒有那麼多,當有人想查看趨勢時,我們會在 Excel 中打開 csv 並根據需要繪製圖表。

事情發展了,我們切換到 MySQL 數據庫。我為每個感測器創建了一個表格(是的,我知道,很多表格!);它一直執行良好,但它有一些局限性。有了這麼多表,顯然不可能編寫一個查詢來在查找特定值時在所有感測器中查找數據。

對於下一個版本,我切換到 Microsoft SQL Server Express,並將所有感測器數據放入一個大表中。這也有效,我們可以通過查詢在所有感興趣的感測器中找到值。但是,我遇到了 Express 版本的 10GB 限制,因此決定切換回 MySQL 而不是投資 SQL Server Standard。

問題

我對 MySQL 的性能和可擴展性感到滿意,但不確定是否堅持使用表中的所有數據是最好的。單表 10GB 似乎要求不同的設計。我應該提到,仍然需要查詢數據以進行繪圖,並且我擔心繪圖查詢會出現性能問題,例如,一個感測器在整個 90 天內的溫度數據。(換句話說,該圖應該是快速生成的東西,無需等待 SQL 對成堆的數據進行排序以隔離感興趣的感測器。)

我應該以某種方式拆分此表以提高性能嗎?或者有這麼大的桌子並不稀奇?

我在 Sensor ID 和 Timestamp 列上有索引,這幾乎是任何查詢的定義邊界。(即從時間 A 到時間 B 獲取感測器 X 的數據)。

我已經閱讀了一些關於分片和分區的內容,但在這種情況下不覺得這些是合適的。


編輯:

根據到目前為止的評論和答案,一些額外的資訊可能會有​​所幫助:

**不是無限期儲存:**目前我不儲存過去 90 天的數據。每天,我都會執行一個查詢來刪除超過 90 天的數據。如果將來變得重要,我會儲存更多,但現在就足夠了。這有助於控制大小並提高性能。

**引擎類型:**最初的 MySQL 實現使用 MyISAM。這次為新實現創建表時(一個數據表而不是多個),它們預設為 InnoDB。我不相信我對其中一個有要求。

**規範化:**除了數據採集表,當然還有其他的表。這些支持表儲存諸如感測器的網路資訊、使用者的登錄資訊等內容。沒有太多需要規範化的內容(據我所知)。數據表有這麼多列的原因是每個感測器都有很多變數。(多個溫度、光照水平、氣壓等)正規化對我來說意味著沒有冗餘數據或重複組。(至少對於 1NF。)對於給定的感測器,在特定時間儲存所有值需要一行數據,並且其中不涉及 1:N 關係(我看到了)。

我可以在功能上拆分錶格,在一個表格中製作(例如)所有與溫度相關的值,在另一個表格中製作所有與氣壓相關的值。雖然這可能會提高僅進行溫度查詢的人的效率,但我仍然必須一次插入所有數據。儘管如此,對於 SELECT 操作來說,效率提升可能是值得的。顯然,我最好根據使用者請求數據的頻率垂直拆分錶格。也許這就是我應該做的。我想在問我的問題時,我正在尋找確認這樣做是值得的。


編輯2:

**數據使用:**最終,大部分數據從未被查看或需要,因為我們通常只關注有問題的項目。但在嘗試發現問題時,我們使用各種工具來搜尋數據並確定要放大哪些項目。

例如,我們注意到記憶體使用值(客戶特定的專有軟體程序)和重啟/崩潰之間的相關性。我收集的其中一個數據點與此記憶體使用量有關,並且我能夠查看歷史數據以顯示在超出特定記憶體使用量後設備變得不穩定。今天,對於執行此軟體的設備子集,我檢查此值並在它過高時發出重啟命令。在發現這一點之前,我認為收集這些數據沒有價值。

出於這個原因,我堅持要收集和儲存大約 100 個數據點,即使值有問題。但在正常的日常使用中,使用者通常會檢查十幾個這樣的參數。如果使用者對特定地理區域感興趣,他可以(使用軟體)為可能幾十個感測器生成數據圖表或電子表格。查看 30 天的圖表並不少見,其中包含兩到三條繪圖線,顯示溫度、氣壓和光照水平等內容。這樣做會執行類似於以下的查詢:

SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);

(在最初的 MySQL 版本中,每個感測器都有自己的表,會發出三個單獨的查詢,但結果會在軟體中組合以創建圖形。)

因為該data表包含如此多的行(約 1000 萬行),儘管在id和上有索引data_timestamp,但性能明顯比多表場景差(在 9 秒內返回 4500 行,而本範例不到 1 秒)。在多表模式中,找到滿足特定標準的感測器的能力實際上為零,因此是移動到單個表的原因。

這種類型的查詢可以由多個使用者快速連續完成,因為他們選擇不同的數據組並比較每個結果的圖表。每個圖表或電子表格等待近 10 秒可能會非常令人沮喪。

數據在 90 天后被丟棄。它可以存檔,但目前不是必需的。

希望這些資訊有助於更充分地展示數據在收集和儲存後的使用方式。

您應該出於一個重要原因考慮對錶進行分區。

您在一張巨表上擁有的所有索引,即使只是一個索引,也會產生大量 CPU 負載和磁碟 I/O,只是在執行 INSERT、UPDATE 和 DELETE 時執行索引維護。

早在 2011 年 10 月 7 日,我就寫過一篇關於為什麼表分區會有很大幫助的文章。這是我過去文章的摘錄:

數據分區應該用於對在同一類中邏輯和內聚的數據進行分組。只要數據被正確分組,搜尋每個分區的性能不必是主要考慮因素。一旦你實現了邏輯分區,然後專注於搜尋時間。如果您僅按 id 分隔數據,則可能永遠不會訪問許多數據行以進行讀取或寫入。現在,這應該是一個主要考慮因素:找到所有最常訪問的 id 並按其進行分區。所有不經常訪問的 id 都應該駐留在一個大存檔表中,該存檔表仍然可以通過索引查找來訪問“藍月亮”查詢。

你可以稍後閱讀我的整篇文章。

為了切入正題,您需要研究並找出在您的 10GB 表中很少使用的數據。如果您需要針對歷史性質的即席查詢,則該數據應放置在易於訪問的存檔表中。從 10GB 遷移該檔案,然後OPTIMIZE TABLE在 10GB 表上遷移,可以生成執行 SELECT、INSERT、UPDATE 和 DELETE 更快的工作集。即使是 DDL 在 2GB 工作集上的執行速度也比 10GB 表要快。

更新 2012-02-24 16:19 EDT

需要考慮的兩點

  1. 從您的評論來看,聽起來您可能需要標準化。
  2. 您可能需要將超過 90 天的所有內容遷移到存檔表中,但仍要同時訪問存檔和工作集。如果你的數據都是 MyISAM,我推薦使用 MERGE 儲存引擎。首先,您創建合併工作集 MyISAM 表和歸檔 MyISAM 表的 MERGE 表映射。您會將少於 91 天的數據保留在一個 MyISAM 表中,並將任何超過 90 天的數據滾動到存檔中。您將只查詢 MERGE 表映射。

這是我關於如何使用它的兩篇文章:

這是我在有很多列的表格上發表的另一篇文章

MySQL中的列太多

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