2013-10-01 36 views
1

我有一種感覺,我會得到屠殺的問這個問題,但在這裏它去...MySQL的設計對於高頻計費系統

我有500萬周,每天的訂閱&期望/希望有5000萬的12個月。我需要非常迅速地續訂/收費。我試過了我能想到的循環索引&的每個排列,但是它的SELECT查詢仍然太慢。也許我的錯誤是MySQL設計,也許它是我使用MySQL的守護進程,也許是因爲我在使用MySQL--請讓我知道你的想法和/或建議。謝謝!

**訂閱表看起來像這樣**

  • subscription_id(PK)
  • subscriber_id
  • 的service_id
  • add_date
  • current_start_date
  • current_end_date
  • bill_date(用於確保兩個線程不搶佔賬單在同一時間)
  • last_successful_bill_date
  • has_outstanding_balance

**錢,人欠,我的表看起來像這樣*

  • ID
  • subscription_id(UK)
  • outstanding_balance
  • next _bill_date
  • number_bill_attempts
  • (人相當數量的不總是付出,我給他們一點未付的訪問,同時我繼續嘗試法案,最終我切斷他們的服務雖然)

**開票守護程序看起來像這樣**

  • 運行多線程在多臺機器:
  • 對於每個服務
    • stuffToBill [] =選擇東西ORDER BY next_bill_date FOR UPDATE LIMIT XXX;
    • UPDATE東西SET next_bill_date =後來WHERE ID IN(stuffToBill [IDS])
    • COMMIT
    • 它們放在一個隊列計費工人

運行EXPLAIN顯示我使用體面的索引,但SQL的實質以及我在多臺服務器上運行相同的守護進程的事實使得它鎖定/通常超載了我的DBM上的I/O隊列。 DBM是高質量的硬件。

再次感謝您的建議!

+1

你寫道:「我需要非常迅速地更新/清點這些。」對於您所描述的規模的系統而言,這是一個不足的性能規範。你需要弄清楚你真的需要這個系統的速度有多快。您需要確定哪些操作需要實時發生(在您的用戶等待期間)以及哪些操作(如果有的話)可以在隔夜計費運行中發生。 –

+0

儘可能快,但如果我可以在幾個小時內完成循環,收益遞減。用戶不在等待。謝謝! – gfunk

回答

1

你似乎可以用一個選擇/更新/承諾制度,以確定哪些帳戶議案,具體如下:

 SELECT stuff 
    ORDER BY next_bill_date 
FOR UPDATE 
    LIMIT XXX; 

    UPDATE stuff 
     SET next_bill_date = later 
    WHERE id IN (stuffToBill[ids]); 

    COMMIT; 

你的SELECT語句可以通過添加一個可行WHERE條款,只有選擇票據來改善該即將到期,或通過其他標準。查看所有賬單只是爲了找到最古老的賬單是沒有意義的。類似於

WHERE next_bill_date <= TODAY() + INTERVAL 30 DAYS 

可能會訣竅。如果你做對了,SELECT查詢的複雜性將會降低。如果你正確的索引next_bill_date,你將會使用索引。

您也可以嘗試使用LIMIT BY xxxx值的大小。您可能在這裏使用的值太大,而且您的更新速度令人不快。

最後,你將需要考慮做一些嚴重的MySQL和InnoDB調優。控制RAM使用等預設參數通常不適合像您這樣的生產系統。

+0

謝謝。我不得不貶低查詢,但它在賬單日期確實有一個where子句和索引。我複製了其他各種機器的數據庫,並對不同的查詢和索引進行了排列 - 但基準測試顯示,對於超過500萬行的縮放,性能提升最小。對設計模式,存儲緩存或其他聰明想法有什麼想法?再次感謝。 – gfunk

+0

緩存不會幫助,因爲您必須讀取並寫入行。緩存有助於多次讀取。設計模式:應該可以避免使用每個查詢對所有行進行掃描和排序。 –

+0

感謝Ollie,任何關於設計模式的建議?分區,更改代碼等等,再次感謝! – gfunk