2011-08-31 102 views
4

我已經分配了一些任務,爲一個網站創建一些圖形統計數據,並保存了一些數據。php mysql優化

Facts: - 有3個數據庫在使用。 dbCurrent,dbStats,dbBackup。 dbCurrent是網站的主要數據庫 dbStats包含各種統計和跟蹤數據表 dbBackup包含過去五年的統計/跟蹤表。

  • 我將使用來自兩個數據庫中的數據(dbStats,DBBACKUP)
  • 表名是:stats2006,stats2007,stats2008等,除了目前的統計這僅僅是 「統計」。每個表格都有其年份的數據。
  • 每年數據的表結構是相同的: primaryID字段是整數 產品id字段是整數 dateMonitor字段是整數(unixtimestamp) 頁面名字段爲varchar(20)
  • 的productID,dateMonitor,頁面名字段也有索引

換句話說,什麼產品在什麼日期和什麼頁面被查看。

所以,我認爲是創建一個循環出每個表並獲取我的數據。 我的每一個查詢看起來像:

Select COUNT(primaryID) as myCounter FROM $tablename WHERE $conditions 

其中$表名和$條件是基於每一個循環變量。 所有條件類似於:

  • 和DATE1之間dateMonitor DATE2
  • 頁面名= '一些VAL'
  • 的productID IN($ comma_separated_values)上述

所有

  • 組合目前爲止,這些產品的體積都很好(單一產品)。

    當我嘗試在'y'年(從admin/moderator動態選擇)中創建比較'x'產品的報表時,腳本運行超過15分鐘。

    我正在尋找一種方法來改善腳本的性能。 邏輯/結構我使用至今,如下:

    Loop through products to find the ids to use (typical format is: x,y,z (comma separated values) 
    Open Loop through years/months 
    Execute one sql query for each affected table/database to get the number of affected rows. 
    Close year loop 
    Send data to graph script (jquery jqPlot to be exact) to print on screen 
    

    任何幫助/想法理解。

    編輯: 基於@Narf建議與UNION ALL,我構建了一個基於12個子選擇語句1個單查詢:

    SELECT COUNT(*) AS monthlyTotal FROM db1.table1 WHERE dateMonitor>='1167606001' AND dateMonitor<='1170284399' AND dateMonitor='test' 
    UNION ALL 
    SELECT COUNT(*) AS monthlyTotal FROM db1.table2 WHERE dateMonitor>='1170284401' AND dateMonitor<='1172703599' AND dateMonitor='test' ... 
    

    每個SELECT語句是指單月時間。演示代碼:

    for ($m=1; $m<=12; $m++) 
    { 
    $startDate = mktime(0, 0, 1, $m, 1, $myYear); 
    $daysOfMonth = date("t", mktime(10, 10, 10, $m, 10, $myYear)); 
    $endDate = mktime(23, 59, 59, $m, $daysOfMonth, $myYear); 
    
    $query_chk1 .= "SELECT COUNT(*) AS monthlyTotal FROM db1.table1 WHERE dateMonitor>='$startDate' AND dateMonitor<='$endDate' AND pageName='test' UNION ALL "; 
    } 
    
    $query_chk1 = substr($query_chk1, 0, -10); 
    

    EDIT2:創建組合索引(由@ypercube所建議的)後,我看到在執行時間一些輕微的下降時間。

    現在我有11分鐘的平均執行時間(原來的時間爲15-17分鐘)

    這幫助了很多以減少執行時間。

    謝謝。

  • +0

    你有什麼指標在桌子上? –

    +1

    另外還有一個提示:與COUNT(字段)相比,MySQL中的COUNT(*)更快。並且給出相同的結果,只要'field'不可爲空。 –

    +0

    @ypercube:productID,dateMonitor,pageName字段是每個表中的索引 – andrew

    回答

    1

    沒有太多可以做的,至少因爲你已經索引的所有列...這裏是最好的,我可以想出:

    SELECT COUNT(*) 
    FROM `stats` 
    WHERE `productID IN(1,2,3) 
        AND `dateMonitor` >= <unixtime from> 
        AND `dateMonitor` <= <unixtime to> 
        AND `pageName`='<value>' 
    

    ...如何:

    • 由於ypercube評論 - 使用COUNT(*)更快。
    • 我不知道這是肯定的,但我相信使用>=<=而不是BETWEEN整數應該更快。

    您應該嘗試的另一件事是一次執行所有查詢(如果有多個)。我很難用文字來正確解釋它,而且我看到你對SQL有很好的把握,所以你應該能夠得到邏輯,所以這裏有一個例子:

    假設我們需要之前

    • 我們計算的時間戳來生成查詢,並準確地確定我們需要哪些表:搜索產品的123,13,5和6,從2006年5月至2008年4月,和頁面名稱「測試」 IDS搜索英寸

      SELECT COUNT(*)AS myCounter FROM stats2006 WHERE productID IN(5,6,13,123) 和dateMonitor> = 1146430800 AND pageName = '測試'

      /*在這裏我們只需要檢查對5月1日的時間戳2006年,00:00 */

      UNION ALL

      SELECT COUNT(*)AS myCounter FROM stats2007 WHERE productID IN(5,6,13,123) 和pageName = '測試'

      /*在這裏我們並不需要檢查dateMonitor場 因爲整個一年我們的期限相匹配 */

      UNION ALL

      SELECT COUNT(*)AS myCounter FROM stats2008 WHERE productID IN(5,6,13,123) 和dateMonitor < = 1209589199 AND pageName = '測試'

      /*在這裏我們只需要檢查時間戳對二零零八年四月三十零日,23:59:59 */

    +0

    謝謝。我不知道UNION ALL語法。從您的示例的快速查看看來,您的sql似乎會生成3個結果。每一個將等於每個選擇語句的受影響行總數。我是否正確地承擔這一點?我還假設,如果我查詢一個月,這種方法會失敗?由於每年每個月的時間戳都不相同,因此每個select語句的COUNT()將導致null或0.在每個WHERE語句中使用不同的條件是否安全? – andrew

    +0

    是的 - 它會產生3個結果,這可能是不正確的,因爲我剛纔注意到您可能需要每個產品的計數,但我不這麼認爲,因爲您的選擇只包含一個計數。這取決於您想要查詢的內容 - 如果您只想獲取例如每年的8月 - 是的,你需要不同的時間戳,但是'UNION'聲明的全部要點是你可以結合兩個不同的查詢結果,所以 - 是的,在'WHERE'中使用不同的標準是安全的聲明。只要生產的柱子是相同的,你可以改變一切。 – Narf

    0

    當你這樣比較「X 'y'年的產品爲什麼不使用GROUP BY?例如:

    Select productID, COUNT(primaryID) as myCounter FROM $tablename WHERE $conditions GROUP BY productID 
    

    這將削減quires的數量,並應加快進程。

    +0

    我認爲小組將會失敗。我不想統計每個產品,而是統計每個產品。例如: 計算某個持續時間內某個頁面中的5種產品的視圖,而相同持續時間內的另一個頁面中的某些其他5種產品的視圖。在網站的當前狀態下,我們不關心單獨的意見,而是關於總數。在稍後的階段,當我們想要檢查哪種產品效率更高時,我們會根據產品/頁面對視圖進行分組來比較它們。 – andrew