【问题标题】:Best log database structure最佳日志数据库结构
【发布时间】:2012-05-18 01:50:40
【问题描述】:

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 

【问题讨论】:

    标签: php mysql performance join


    【解决方案1】:

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

    您在这里只存储一种类型的数据,因此将其存储在一个表中是合适的。在早期阶段,您不必太担心表格会随着时间的推移而增长到多大。像这样的表中只有几列,它可以很容易地增长到数百万行,而您甚至不需要考虑对其进行分区。

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

    【讨论】:

    • 我在考虑随着表大小的增加,因为它记录了所有活动,它有可能非常大,这就是为什么我想确保它仍然更有效率
    • @brianwilson 如果表变得很大,有需要可以考虑partitioning it
    【解决方案2】:

    使用一张表是正确的做法,因为它已正确规范化。添加新事件类型不需要新表。维护参照完整性并利用索引为用户检索和排序所有事件也容易得多。 (如果将它们放在单独的表中,获取用户的所有事件并按时间排序可能比使用一张表要慢得多!)

    但是,您可以通过一些方法使这些表更小,以节省空间并保持索引更小:

    • 使用enum() 定义您的事件类型。如果您有少量事件,则每行最多使用一个字节。
    • 使用UNSIGNED 整数类型可在相同字节数中获得更多EventIDUserIDs。
    • 如果您不需要完整的日期范围(可能),请使用 TIMESTAMP 类型与 DATETIME 类型相比,每行节省 4 个字节。
    • 如果您只使用 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 ? 这样的查询会非常快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-17
      • 2023-04-08
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      相关资源
      最近更新 更多