2012-05-18 58 views
1

MYSQL/PHP,我想創建一個人們在網站上執行的活動的記錄。最好的日誌數據庫結構

Table ADDED -> EventID, UserID, Time, IP 

Table DELETED -> EventID, UserID, Time, IP 

Table SHARED -> EventID, UserID, Time, IP. 

是不是更有效地查詢到例如讀取由USERID執行的最後10個動作時,加入這些表,或者這將是更有效的結構是這樣的。

Table EVERYTHING -> EventID, EventType(eg ADDED, DELETED, SHARED), UserID, Time, IP 

回答

1

使用一個表是這樣做,因爲它是正確歸正確的事情。添加新的事件類型不應該需要新的表格。維護參照完整性並利用索引來檢索和排序用戶的所有事件也容易得多。 (如果你把它們放在單獨的表格中,爲一個用戶獲取所有事件並按時間排序可能會比使用一個表格慢得多)

雖然有很多方法可以使這些表格更小空間並保持您的索引較小:

  • 使用enum()定義您的事件類型。如果您的事件數量很少,則每行最多使用一個字節。
  • 使用的UNSIGNED整數類型,以獲得更多EventIDUserID出去了相同的字節數。
  • 如果您不需要全部日期範圍(可能),請使用TIMESTAMP類型來爲每個行節省4個字節,而不是DATETIME類型。
  • 如果你只使用IPv4地址,存儲IP作爲一個無符號的4字節整數,並使用INET_ATON()和INET_NTOA()來回轉換。這是這裏最大的贏家:VARCHAR類型至少需要16個字節,並且您可以使用固定的行長度格式。

我推薦一個表格式是這樣的:

CREATE TABLE Events (
    `EventID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, 
    `UserID` MEDIUMINT UNSIGNED NOT NULL COMMENT 'this allows a bit more than 16 million users, and your indexes will be smaller', 
    `EventType` ENUM('add','delete','share') NOT NULL, 
    `Time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `IP` INTEGER UNSIGNED NOT NULL DEFAULT 0, 
    PRIMARY KEY (`EventID`), 
    FOREIGN KEY (`UserID`) REFERENCES `Users` (`UserId`) ON UPDATE CASCADE ON DELETE CASCADE, 
    KEY (UserID) 
); 

如果該存儲使用MyISAM的,你行的長度將是16個字節,使用固定格式。這意味着每百萬行需要16MB的空間用於數據,可能大約是索引的一半(取決於您使用的索引)。這非常緊湊,因此大多數情況下,mysql可能會將整個表的工作部分保留在內存中。

然後,它的創建你需要的是最常見的操作指標的問題。例如,如果您始終在特定時間範圍內顯示所有用戶的活動,請將KEY (UserID)替換爲INDEX userbytime (UserID, Time)。那麼像SELECT * FROM Events WHERE UserID=? AND Time BETWEEN ? AND ?這樣的查詢將會非常快。

3

使用一個表記錄所有事件並區分事件類型,如第二個建議中所述。

您在這裏只存儲一個類型的數據,並因此,有必要將其存儲在一個表中。在早期階段,你不應該太擔心桌子隨着時間的推移而增長的規模。在這樣的表格中只有幾列,在您甚至需要考慮對其進行分區之前,它可以輕鬆地增長到數百萬行。

如果有事件類型的數量有限,您可以考慮使用the ENUM() data typeEventType列。

+0

我認爲隨着桌子尺寸的增長,它會記錄所有的活動,它有可能會非常大,這就是爲什麼我想確保它更高效 –

+0

@brianwilson如果桌子變得非常大,如果需要,你可以考慮[分區](http://dev.mysql.com/doc/refman/5.1/en/partitioning.html)。 –