最佳日志数据库结构

时间:2012-05-18 01:50:41

标签: php mysql performance join

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 

2 个答案:

答案 0 :(得分:3)

使用一个记录所有事件的表并区分事件类型,如第二个建议所示。

此处只存储一种类型的数据,因此将其存储在一个表中是合适的。在早期阶段,你不应该担心桌子随着时间的推移会变大。在这样的表中只有几列,它甚至可以容易地扩展到数百万行,甚至不需要考虑对它进行分区。

如果您的事件类型数量有限,则可以考虑将the ENUM() data type用于EventType列。

答案 1 :(得分: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 ?这样的查询会非常快。