2011-10-06 43 views
0

我們剛剛構建了一個系統,可在午夜彙總其數據。它必須遍歷多個表的組合才能彙總所需的數據。不幸的是,UPDATE查詢正在持續進行。我們擁有我們預測的用戶數的1/1000,每天只需要28分鐘即可彙總我們的測試用戶數據。使用MySQL巨大更新進行擴展

由於主要延遲是UPDATE查詢,可能很難委派服務器來處理數據處理。對於優化數百萬個UPDATE查詢有什麼其他選擇?我的縮放問題是否在下面的代碼中?:

 $sql = "SELECT ab_id, persistence, count(*) as no_x FROM $query_table ftbl 
       WHERE ftbl.$query_col > '$date_before' AND ftbl.$query_col <= '$date_end' 
       GROUP BY ab_id, persistence"; 

     $data_list = DatabaseManager::getResults($sql); 

     if (isset($data_list)){ 
      foreach($data_list as $data){ 

       $ab_id = $data['ab_id']; 
       $no_x = $data['no_x']; 
       $measure = $data['persistence']; 

       $sql = "SELECT ab_id FROM $rollup_table WHERE ab_id = $ab_id AND rollup_key = '$measure' AND rollup_date = '$day_date'"; 
       if (DatabaseManager::getVar($sql)){ 
         $sql = "UPDATE $rollup_table SET $rollup_col = $no_x WHERE ab_id = $ab_id AND rollup_key = '$measure' AND rollup_date = '$day_date'"; 
           DatabaseManager::update($sql); 
       } else { 
         $sql = "INSERT INTO $rollup_table (ab_id, rollup_key, $rollup_col, rollup_date) VALUES ($ab_id, '$measure', $no_x, '$day_date')"; 
           DatabaseManager::insert($sql); 
       } 
      } 
     } 
+0

你有沒有想過[複製](http://dev.mysql.com/doc/refman/5.0/en/replication.html)? –

+0

您的SELECT查詢需要多長時間才能在沒有UPDATE或INSERT語句的情況下進行處理?那些可能解決你的性能問題的瓶頸可能會有更大的瓶頸嗎?是否有必要在PHP源代碼級而不是MySQL存儲過程級上遍歷數據?是否有必要通過記錄迭代程序,還是有可能通過基於集合的操作完成相同的事情? –

+0

要回答@ Shan的問題:SELECT需要很少的時間。你有沒有在「MySQL程序級別」或「基於集合」操作的例子中這樣做的例子?我現在正在尋找喬伊的鏈接 – Kyle

回答

2

解決SQL擴展問題時,最好總是對有問題的SQL進行基準測試。即使在PHP級別,在這種情況下也可以,因爲您在PHP中運行查詢。

如果您的第一個查詢可能會返回數百萬條記錄,那麼可以更好地將該查詢作爲MySQL存儲過程運行。這將最大限度地減少數據庫服務器和PHP應用程序服務器之間必須傳輸的數據量。即使兩臺機器都是同一臺機器,您仍然可以實現顯着的性能提升。

一些需要考慮的問題,可能有助於解決您的問題如下:

  • 多久你的SELECT查詢需要沒有UPDATE或INSERT語句來處理?
  • 什麼是您的查詢的百分比細分 - 通過SQL選擇和INSERT和UPDATE?使用該信息幫助確定解決方案將更加容易。
  • 有可能是那些可能解決您的性能問題的瓶頸有更大的瓶頸?
  • 是否有必要在PHP源代碼級而不是MySQL存儲過程級別迭代數據?
  • 是否有必要通過記錄迭代程序化,還是可以通過基於集合的操作完成相同的事情?
  • 您的rollup_table是否具有覆蓋UPDATE查詢中列的索引?
  • 此外,SELECT查詢在您的UPDATE查詢似乎具有相同的WHERE子句之前運行。這似乎是一種冗餘。如果你只能運行WHERE子句一次,那麼你會爲你的最大瓶頸削減很多時間。

如果你不熟悉編寫MySQL存儲過程,這個過程很簡單。以http://www.mysqltutorial.org/getting-started-with-mysql-stored-procedures.aspx爲例。 MySQL也有很好的文檔。存儲過程是一個在MySQL數據庫過程中運行的程序,當處理可能返回數百萬行的查詢時,這可能有助於提高性能。

基於集合的數據庫操作通常比程序操作更快。 SQL是一種基於集合的語言。您可以使用單個UPDATE語句更新數據庫表中的所有行,即更新客戶SET total_owing_to_us = 1000000更新customers表中的所有行,而不需要像您在示例代碼中創建的那樣創建程序循環。如果您擁有100,000,000個客戶條目,則基於集合的更新將比程序更新快得多。網上有很多有用的資源,你可以閱讀這些資源。下面是一個SO鏈接:Why are relational set-based queries better than cursors?