簡體   English   中英

正確的方法來創建動態1:M SQL表

[英]Proper way to create dynamic 1:M SQL table

簡化示例:兩個表 - 人和時間。 目標是跟蹤一個人走過門口的所有時間。

一個人每天可以在時間表中有0到50個條目。

跟蹤這些記錄的正確和最有效的方法是什么? 是嗎

times table
-----------
person_id
timestamp

我擔心這張桌子可以很快地獲得超過一百萬條記錄。 插入和檢索時間至關重要。

另外:顯然非標准化,但這樣做會更好

times table
-----------
person_id
serialized_timestamps_for_the_day
date

我們需要訪問該人的每個時間戳,但只能查詢日期或人員ID的記錄。

考慮一下我們在這里談論什么。 僅考慮原始數據(event_time, user_id)每1M行(4 + 4) * 1M ~ 8MB 讓我們試着在DB中粗略估計一下。

一個整數4個字節,時間戳4個字節; 行標題,比方說18個字節 - 這使行大小的第一個估計值達到4 + 4 + 18 = 26 bytes 使用頁面填充因子約為0.7; ==>每行26 / 0.7 ~ 37個字節。

因此,對於1M行,大約37 MB。 您將需要索引(user_id, event_time) ,所以讓我們簡單地將原始文件翻倍為37 * 2 = 74 MB

這使得非常粗略,無法估計的估計為每1M行74MB。

因此,要始終將其保留在內存中,此表的每1M行需要0.074 GB。

要獲得更好的估計,只需創建一個表,添加索引並用幾百萬行填充它。

鑒於預期的數據量,即使在筆記本電腦上也可以輕松測試10M行 - 測試總是能夠推測。

PS你的選項2看起來並不是 “明顯更好的主意”

第二種解決方案存在一些問題:

  • 由於您需要訪問單個時間戳1serialized_timestamps_for_the_day不能被視為原子並且會違反1NF,從而導致一系列問題
  • 最重要的是,您引入了冗余:可以從serialized_timestamps_for_the_day的內容推斷出date ,並且您的應用程序代碼需要確保它們永遠不會變得“失去同步”,這很容易受到錯誤的影響。 2

因此,請使用第一個解決方案。 如果正確編制索引 ,現代硬件上的現代數據庫可以處理的不僅僅是“超過一百萬條記錄”。 在這個特定情況下:

  • {person_id,timestamp}上的復合索引將允許您通過簡單的索引范圍掃描查詢人員或人與日期的組合,這可能非常有效。
  • 如果您只需要“按日期”查詢,則需要{timestamp}上的索引。 通過搜索給定日期的00:00到24:00,您可以輕松搜索特定日期內的所有時間戳。

1即使您不查詢單個時間戳,仍需要逐個將它們寫入數據庫。 如果您有序列化字段,則首先需要讀取整個字段以僅附加一個值,然后將整個結果寫回數據庫,這可能會很快成為性能問題。 還有其他問題,如上面的鏈接所述。

2作為一般規則,除非有良好的表現理由,否則不應存儲可推斷的內容 ,我在此處看不到任何內容。

我認為第一種選擇是更好的選擇。

即使您選擇第二個選項,索引的大小也可能不會減少。 實際上會有一個額外的專欄。

並且不同用戶的數據無關,可以根據person_id對數據庫進行分片。 即,假設您的數據不適合單個數據庫服務器節點,並且需要兩個節點。 然后,一半用戶的數據將存儲在一個節點上,其余數據將存儲在另一個節點上。

這可以使用像MySQL這樣的RDBMS或像MongoDBOrientDB這樣的面向文檔的數據庫來完成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM