2013-07-16 42 views
0

我有一個腳本,用於查詢50,000條記錄的數據庫,並嘗試創建一個表,概述每星期每週向數據庫中添加新條目的每週報告。使用php優化多周mysql查詢

我有一個約束:報告必須從$START_DATE開始,這是網站每個部分下數據庫中任何用戶的第一天存在記錄。這意味着我不能使用查找預定義日期的函數,我必須計算第一個用戶輸入數據庫的部分中的用戶,直到一個星期後,直到$END_DATE(通常是time())爲止。

大約需要5秒查詢數據庫的count(*)select *

mysql> select count(*), user_type from users_table where user_permissions = "normal" group by user_type; 
+----------+-----------------+ 
| count(*) | user_type  | 
+----------+-----------------+ 
|  2210 | myspace_user | 
| 48659 | facebook_user | 
+----------+-----------------+ 
2 rows in set (4.73 sec) 

我有,通過雲和查詢數據庫中的一堆每user_type次一些PHP代碼來獲得的詳表每週報告。問題是,有12個星期和兩個用戶類型,因此整個過程最多需要兩分鐘。網站的某些部分有兩種以上的用戶類型,這些查詢需要更長的時間。下面的代碼:

$start = strtotime($START_DATE); 
$end = strtotime($END_DATE); 
for ($i = 0; $start+$i < time() && $start+$i < $end; $i+= (7*24*60*60)) { 
    $weekly_total = 0; 
    foreach($USERTYPES as $usertype) { 
     $q = "select count(*) from users_table where user_type = '" . $usertype . "' and user_permissions = 'normal'"; 
     $q .= " and UNIX_TIMESTAMP(timestmp) >= " . strval($start+$i) . " and UNIX_TIMESTAMP(timestmp) <= " . strval($start+$i+(7*24*60*60)); 
     $r = mysql_query($q); 
     $v = mysql_fetch_array($r); 
     $table['weekly'][gmdate("Y-m-d", $start+$i)][$usertype] += $v[0]; 
     $weekly_total += $v[0]; 
    } 
    $table['weekly'][gmdate("Y-m-d", $start+$i)]['weekly_total'] = $weekly_total; 
} 

最後我有12個條目,像這樣的僞代碼結束的陣列,具有基本結構:

// ...previous entries 
$table['weekly']['2013-07-01'] = array(
    'myspace_user' => 123, 
    'facebook_user' => 1234, 
    'weekly_total' => 1357 
); 
$table['weekly']['2013-07-08'] = array(
// ...and so on 

,其產生這些查詢,並將它們保存到該表的過程需要很長時間。有什麼辦法可以使MySQL或PHP函數更高效,所以我不必爲每週生成一個單獨的查詢?

回答

0

你的代碼效率非常低,迫使在fence(PHP和MySQL)兩邊進行多個日期 - >時間戳轉換。爲什麼不能有一個更簡單的

$start = '2013-07-16'; 

for ($week = 0; $week < 52; $week++) { 
    SELECT ... 
    ... 
    WHERE timestmp BETWEEN ($start + INTERVAL $week WEEK) 
     AND ($start + INTERVAL $week WEEK + INTERVAL 7 DAY) 
} 

你會堅持使用本土的MySQL日期時間值,沒有所有的重複native->內部 - > native->任何轉換。

+0

這些SELECT查詢中的每一個需要4.75秒,與我的完全相同。計算兩種類型12周的整個過程仍需要2分鐘。從int到字符串的date-> timestamp轉換花費的時間可以忽略不計,並且用於顯示目的(也因爲我無法控制某些數據如何到達我家門口)。 – Joey

+0

你也可以通過只有最低/最高可能的日期範圍,並提取一個派生字段,例如'WEEK(timestmp)',以便確定記錄應該處於哪個時期,從而將其減少爲單個查詢。 –

+0

@joey :如果SELECT本身需要4.75秒,那麼表的結構可能有問題......有多少條記錄? 'user_type'編入索引了嗎?也許'user_permissions'是一個字符串?在這裏做出錯誤的選擇會影響你的查詢。 – JvO