我有一个PHP页面做1000个SQL查询。它为用户列表提供已发生事件的统计信息。页面加载时间有点长(现在索引调整后需要6秒)。我想知道是否有另一种/更好的方法来做到这一点,而不是1000个单独的查询。有没有更快的方法,特别是随着数据的增长。
这1000个SQL查询的结果被放入PHP数组,并最终填充html表的单元格,如下所示:
Installs Called Early Install Event4 Event5 (... 9
George 5 6 3 5 29 different event
Greg 9 7 1 8 23 types, up to
David 4 1 2 4 0 maybe 15
Dan 15 17 4 20 10 eventually)
... ... ... ... ... ...
... ... ... ... ... ...
Totals 351 312 82 289 1220
(... there are up to ~50 users, maybe 100 total in the next two years)
有些列实际上是在PHP中从数据(event4/安装)*100中动态计算出来的百分比。
表总是在给定的数据范围内,例如:
选择日期范围:Dates Jan 15, 2013 - March 31, 2013
.
event
表的字段:id, event_type, user_id, event_date
数据本身存储为一个由特定日期发生的事件组成的表。PHP页面最常见的SQL语句类型是计数查询,如下所示:
SELECT COUNT(id)
FROM events
WHERE userid = 10
AND `event_date` BETWEEN '2013-01-01' AND '2013-02-15'
AND event_type = 'Install';
SELECT COUNT(id)
FROM events
WHERE userid = 10
AND `event_date` BETWEEN '2013-01-01' AND '2013-02-15'
AND event_type = 'Called';
SELECT COUNT(id)
FROM events
WHERE userid = 10
AND `event_date` BETWEEN '2013-01-01' AND '2013-02-15'
AND event_type = 'Early Install';
/* and so on for each event type and user id */
这些计数()填充html表的单元格。它在一个php循环中执行这些计数(),该循环遍历每个用户(表示html输出表中的每一行),并在每行中遍历每个事件类型(列),并为每个事件类型执行COUNT
。~50个用户,~10个事件类型,你在一个页面上得到大约~1000个单独的SQL请求。
- 是否有一个合理的方法来结合所有这些单独的SQL
COUNT
操作或做这一切更快或更正确没有所有的单独的COUNT
调用来自PHP?也许是一个存储过程……明白了吗?如果是这样,如何处理(一堆计数查询或游标或什么)?如何从存储过程构造/返回计算计数数据的后行?
我不是要你回答整个问题,而是要你回答你可能回答的那一部分,或者你会怎么做。
还有(#2)这些东西是如何缓存的?缓存通过把所有的COUNT值PHP,然后写这些值从PHP到mysql表与行每个用户和每个日期范围,或缓存在某处/以某种方式其他?
我想到了分组。
SELECT userid, event_type, COUNT(id) AS cnt
FROM events
WHERE `event_date` BETWEEN '2013-01-01' AND '2013-02-15'
GROUP BY userid, event_type
ORDER BY userid, event_type
这将返回一个数组,其中每行的结构大致为:
array(
userid=>10,
event_type=>'Installs',
cnt=>5
);
你可以遍历它来构建你的表。
//iterate over the data first constructing a new array for below
$newData = array();
$headers = array();
foreach($data as $row){
//save the data in a multi dimensional array under the userid
if(!isset($newData[$row['userid']])){
$newData[$row['userid']]=array();
}
$newData[$row['userid']][$row['event_type']] = $row['cnt'];
$headers[$row['event_type']]=1;
}
//get the headers
$headers = array_keys($headers);
//display the data for debugging
echo '<pre>'.print_r($newData,1).'</pre>';
echo "<table colspan=0 cellspacing=0 border=1>n";
//add "user id" to the headers
array_unshift($headers, "User ID");
//echo the headers
echo "t<thead>ntt<th>".implode("</th>ntt<th>", $headers)."</th>nt</thead>n";
//remove the user id column from headers
array_shift($headers);
echo "t<tbody>n";
//now loop over the new data and display.
foreach($newData as $userID=>$row){
//start row
echo "tt<tr>n";
//user id
echo "ttt<td>{$userID}</td>n";
//loop over the headers. there should be corresponding keys for each header
foreach($header as $key){
//get the count if the key exists and '-' if not.
$cnt = isset($row[$key])?$row[$key]:'-';
echo "ttt<td>{$cnt}</td>n";
}
echo "tt</tr>n";
}
echo "t</tbody>n</table>n";
应该是这样的。
SELECT
userid,
event_type,
COUNT(id)
FROM
events
WHERE
`event_date` BETWEEN '2013-01-01' AND '2013-02-15'
GROUP BY 1, 2
编辑:这只是部分答案。我不是缓存方面的权威:)对不起,我帮不上忙。