Mysql:索引计数查询与维护摘要table
Mysql: indexed count query vs maintaining summary table
我在一个电子商务网站上工作,用户可以在该网站上对可用产品表现出兴趣,我们将其作为潜在客户存储在 mysql table 中。此 Leads
table 包含数百万条记录,并且每秒增长 8 条记录。 Table结构如下:
LeadId | ProductId | UserId | RequestDate(DateTime)
Table 架构:
`id` int(11) NOT NULL AUTO_INCREMENT,
`ProductId` int(11) DEFAULT NULL,
`UserID` int(11) NOT NULL,
`RequestDateTime` datetime(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_leads_requestdatetime` (`RequestDateTime`) USING BTREE,
KEY `ix_leads_productid` (`ProductId`) USING BTREE,
KEY `ix_leads_userid` (`UserID`) USING BTREE
现在,要求是允许一个用户在一天内最多提供 10 个潜在客户。我有以下方法来实现这个:
Select 查询计算 Leads
table 中当天的记录数,并在插入前检查是否 < 20。
维护一个 DailyLeadCount
table,其中包含特定日期每个 userId
的潜在客户数量。 Table结构:
UserId | Date | Count
Table 架构:
`RequestDate` date NOT NULL,
`UserId` int(11) NOT NULL,
`LeadCount` smallint(6) NOT NULL,
PRIMARY KEY (`RequestDate`,`UserId`)
我将在插入 Leads
table 之前检查此 table 中的计数,并在插入后相应地更新此计数。此外,由于此 table 中只有一天的数据有用,我将创建一个作业来每天存档它。
哪种方法更好? 运行 select 在 Leads
table 上的查询是否比 insert/update 和 select 在 DailyLeadCount
[=54 上的查询更重=]?
每天维护和归档 table 是否值得?
还有其他方法可以解决这个问题吗?
改变
KEY `ix_leads_userid` (`UserID`) USING BTREE
至
INDEX(UserID, RequestDateTime)
然后在
时向用户吐口水
( SELECT COUNT(*) FROM Leads WHERE UserID = 1234
AND RequestDateTime > NOW() - INTERVAL 24 HOUR
) >= 10
查询速度足够快,可以实时进行。
计数是从昨天的这个时间到现在的时间 -- 这可能不是您想要的。相反,如果您希望时钟在今天早上午夜开始:
AND RequestDateTime > CURDATE()
如果"since midnight yesterday":
AND RequestDateTime > CURDATE() - INTERVAL 1 DAY
如果你想在午夜使用他的时区,它会变得更混乱。
潜在问题:如果他能以某种方式批量处理他的销售线索,他可以在同一毫秒内插入多个销售线索。 (我注意到 DATETIME(3)
。)
如果您需要对照 "yesterday" 进行检查,您的摘要想法 Table 最有效,但对于 "the last 86400000 milliseconds".
则效果不佳
我在一个电子商务网站上工作,用户可以在该网站上对可用产品表现出兴趣,我们将其作为潜在客户存储在 mysql table 中。此 Leads
table 包含数百万条记录,并且每秒增长 8 条记录。 Table结构如下:
LeadId | ProductId | UserId | RequestDate(DateTime)
Table 架构:
`id` int(11) NOT NULL AUTO_INCREMENT,
`ProductId` int(11) DEFAULT NULL,
`UserID` int(11) NOT NULL,
`RequestDateTime` datetime(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_leads_requestdatetime` (`RequestDateTime`) USING BTREE,
KEY `ix_leads_productid` (`ProductId`) USING BTREE,
KEY `ix_leads_userid` (`UserID`) USING BTREE
现在,要求是允许一个用户在一天内最多提供 10 个潜在客户。我有以下方法来实现这个:
Select 查询计算
Leads
table 中当天的记录数,并在插入前检查是否 < 20。维护一个
DailyLeadCount
table,其中包含特定日期每个userId
的潜在客户数量。 Table结构:UserId | Date | Count
Table 架构:
`RequestDate` date NOT NULL, `UserId` int(11) NOT NULL, `LeadCount` smallint(6) NOT NULL, PRIMARY KEY (`RequestDate`,`UserId`)
我将在插入
Leads
table 之前检查此 table 中的计数,并在插入后相应地更新此计数。此外,由于此 table 中只有一天的数据有用,我将创建一个作业来每天存档它。
哪种方法更好? 运行 select 在 Leads
table 上的查询是否比 insert/update 和 select 在 DailyLeadCount
[=54 上的查询更重=]?
每天维护和归档 table 是否值得?
还有其他方法可以解决这个问题吗?
改变
KEY `ix_leads_userid` (`UserID`) USING BTREE
至
INDEX(UserID, RequestDateTime)
然后在
时向用户吐口水( SELECT COUNT(*) FROM Leads WHERE UserID = 1234
AND RequestDateTime > NOW() - INTERVAL 24 HOUR
) >= 10
查询速度足够快,可以实时进行。
计数是从昨天的这个时间到现在的时间 -- 这可能不是您想要的。相反,如果您希望时钟在今天早上午夜开始:
AND RequestDateTime > CURDATE()
如果"since midnight yesterday":
AND RequestDateTime > CURDATE() - INTERVAL 1 DAY
如果你想在午夜使用他的时区,它会变得更混乱。
潜在问题:如果他能以某种方式批量处理他的销售线索,他可以在同一毫秒内插入多个销售线索。 (我注意到 DATETIME(3)
。)
如果您需要对照 "yesterday" 进行检查,您的摘要想法 Table 最有效,但对于 "the last 86400000 milliseconds".
则效果不佳