2011-03-09 44 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會忘記緩存的結果並將其重新彙總。 –