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
答案 0 :(得分:3)
使用一个记录所有事件的表并区分事件类型,如第二个建议所示。
此处只存储一种类型的数据,因此将其存储在一个表中是合适的。在早期阶段,你不应该担心桌子随着时间的推移会变大。在这样的表中只有几列,它甚至可以容易地扩展到数百万行,甚至不需要考虑对它进行分区。
如果您的事件类型数量有限,则可以考虑将the ENUM()
data type用于EventType
列。
答案 1 :(得分:1)
使用一个表是正确的,因为它已正确规范化。添加新事件类型不应该需要新表。维护参照完整性并使用索引来检索和排序用户的所有事件也更容易。 (如果你将它们放在不同的表中,为用户获取所有事件并按时间排序可能比使用一个表要慢得多!)
但是,有些方法可以使这些表更小,以节省空间并保持索引较小:
enum()
定义您的活动类型。如果您有少量事件,则每行最多使用一个字节。UNSIGNED
整数类型可以从相同的字节数中获得更多EventID
和UserID
。我推荐这样的表格格式:
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 ?
这样的查询会非常快。