2011-03-09 45 views
0

我需要限制多个客户的多种服务使用。例如,客户客户1可以每月发送最多1000条SMS。我的实现是基于一个MySQL表3列:服务使用限制器实施

date TIMESTAMP 
name VARCHAR(128) 
value INTEGER

对每个服务使用(发送短信)一行插入到表中。 value保存使用次数(例如,如果SMS被拆分为2部分,则value = 2)。 name保存限制器名称(例如,customer1-sms)。

要找出服务中使用多少次这个月(2011年3月),执行一个简单的查询:

SELECT SUM(value) FROM service_usage WHERE name = 'customer1-sms' AND date > '2011-03-01';

的问题是,这个查询慢(0.3秒)。我们在列datename上使用索引。

有没有更好的方法来实现服务使用限制?我的要求是它必须是灵活的(例如,如果我需要知道最近10分钟内的使用情况或当前月份内的使用情况)。我正在使用Java。

在此先感谢

+0

我愿意接受完全不同的解决方案。也许一些内存中并没有使用数据库。或者使用专门为此目的创建的专门数据库。 –

回答

0

我找到了解决我的问题的方法之一。除了插入服务使用增量的,我会插入最后一个递增:

 
BEGIN; 

-- select last the value 
SELECT value FROM service_usage WHERE name = %name ORDER BY date ASC LIMIT 1; 

-- insert it to the database 
INSERT INTO service_usage (CURRENT_TIMESTAMP, %name, %value + %increment); 

COMMIT; 

要了解服务使用自%日期:

SELECT value AS value1 FROM test WHERE name = %name ORDER BY date DESC LIMIT 1; SELECT value AS value2 FROM test WHERE name = %name AND date <= %date ORDER BY date DESC LIMIT 1;

其结果将是值1 - 值2

这样我就需要交易。我可能会实现它作为存储过程。

任何额外的提示仍然赞赏:-)

1

你应该有两列一个指标,对各支柱的不是两个指标。这应该使查询速度非常快。

如果它仍然没有,那么你可以使用一个带有月份,名称和值的表格,并在每次发送短信时增加当前月份的值。这将从您的查询中删除总和。尽管如此,它仍然需要(月,名)的索引尽可能快。

+0

我也尝试过两个列上的索引 - 它没有帮助。 MySQL只在'name'上使用索引,如果日期范围不是太大,它也会使用'date'索引。我用'EXPLAIN SELECT ...'命令检查了这个。 –

+0

您使用月表的解决方案并不像我需要的那样灵活。我还需要在过去24小时内知道使用次数,并且可能会有其他动态查询,其中包含参数名称和过去的某个日期。 –

+0

您是否尝试过在查询中给出结束日期(即'2011-03-01'和'2011-04-01'之间的AND日期),也许它会更改解释计划。这个表中的行数是多少?您是否可以删除旧条目(即当前月份之前)以加快扫描速度? –

0

值得尝试用“like”替换“=”。不知道为什么,但在过去,我已经看到这比varchar列上的“=”运算符的执行速度要快得多。

SELECT SUM(value) FROM service_usage WHERE name like 'customer1-sms' AND date > '2011-03-01'; 

意见后编辑:

好了,现在我可以八九不离十重新创建您的问题 - 我第一次运行查询,约需0.03秒,后续查询的运行采取0.001秒。插入新记录会导致查询恢复到0.03秒。

建议的解决方案: COUNT不显示相同的减速。我会改变业务逻辑,因此每次用户发送和SMS时,都会插入值为“1”的记录;如果消息是多部分消息,只需插入两行即可。 用“计数”替换“总和”。 我已将此应用于我的测试数据,并且即使在插入新记录后,“计数”查询也会在0.001秒内返回。

+0

这没有帮助。 –

+0

你可以在查询的开头添加“explain”吗?我试图重新创建你的数据结构,并用一百万左右的行填充它,并且查询速度很快...... –

+0

后续选择速度很快。但是在插入一行之后,MySQL会忘记缓存的结果并将其重新汇总。 –