2013-07-16 46 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