我一直在编写一个新的仪表板,我想显示各种数据库统计信息,主要是计算行数并将结果设置为变量,它们都正常工作,但是我有点担心这么多的SELECT查询也会变得太多如果很多用户正在进入或刷新页面,那就很重要。
感谢您的意见:)
$tbl_players = players;
$xbox = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'XBOX360'");
$ps3 = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'PS3'");
$pc = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'PC'");
$xbfa = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'XBOX360' && fathread LIKE 'http%'");
$psfa = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'PS3' && fathread LIKE 'http%'");
$pfa = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'PC' && fathread LIKE 'http%'");
$xbcr = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'XBOX360' && crthread LIKE 'http%'");
$pscr = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'PS3' && crthread LIKE 'http%'");
$pcr = mysql_query("SELECT * FROM $tbl_players WHERE Console = 'PC' && crthread LIKE 'http%'");
while($row = mysql_fetch_array($xbox))
{
$cxbox = mysql_num_rows($xbox);
}
while($row = mysql_fetch_array($ps3))
{
$cps3 = mysql_num_rows($ps3);
}
while($row = mysql_fetch_array($pc))
{
$cpc = mysql_num_rows($pc);
}
while($row = mysql_fetch_array($xbfa))
{
$xboxfa = mysql_num_rows($xbfa);
}
while($row = mysql_fetch_array($psfa))
{
$ps3fa = mysql_num_rows($psfa);
}
while($row = mysql_fetch_array($pfa))
{
$pcfa = mysql_num_rows($pfa);
}
while($row = mysql_fetch_array($xbcr))
{
$xboxcr = mysql_num_rows($xbcr);
}
while($row = mysql_fetch_array($pscr))
{
$ps3cr = mysql_num_rows($pscr);
}
while($row = mysql_fetch_array($pcr))
{
$pccr = mysql_num_rows($pcr);
}
$tbl_interactive = interactive;
$maximum = mysql_query("SELECT ID FROM $tbl_interactive ORDER BY ID DESC LIMIT 1");
while($max = mysql_fetch_array($maximum))
{
$cint = $max['ID'];
}
$xboxf = mysql_query("SELECT * FROM $tbl_interactive WHERE Console = 'XBOX360' && Type = 'Player' && $date < EndTime");
$xboxc = mysql_query("SELECT * FROM $tbl_interactive WHERE Console = 'XBOX360' && Type = 'Club' && $date < EndTime");
$ps3f = mysql_query("SELECT * FROM $tbl_interactive WHERE Console = 'PS3' && Type = 'Player' && $date < EndTime");
$ps3c = mysql_query("SELECT * FROM $tbl_interactive WHERE Console = 'PS3' && Type = 'Club' && $date < EndTime");
$pcf = mysql_query("SELECT * FROM $tbl_interactive WHERE Console = 'PC' && Type = 'Player' && $date < EndTime");
$pcc = mysql_query("SELECT * FROM $tbl_interactive WHERE Console = 'PC' && Type = 'Club' && $date < EndTime");
while($row = mysql_fetch_array($xboxf))
{
$xboxfi = mysql_num_rows($xboxf);
}
while($row = mysql_fetch_array($xboxc))
{
$xboxci = mysql_num_rows($xboxc);
}
while($row = mysql_fetch_array($ps3f))
{
$ps3fi = mysql_num_rows($ps3f);
}
while($row = mysql_fetch_array($ps3c))
{
$ps3ci = mysql_num_rows($ps3c);
}
while($row = mysql_fetch_array($pcf))
{
$pcfi = mysql_num_rows($pcf);
}
while($row = mysql_fetch_array($pcc))
{
$pcci = mysql_num_rows($pcc);
}
非常感谢!
答案 0 :(得分:3)
我会确保你有适当的指数(索引,如果你愿意)。
此外,您可能希望使用COUNT而不是选择大量行,然后仅使用行计数。这是因为像这样的查询:
SELECT * FROM $tbl_players WHERE Console = 'XBOX360'
...正在发送大量数据,由于您没有使用它,这浪费了带宽和不必要的额外加载时间。最好配合:
SELECT COUNT(*) FROM $tbl_players WHERE Console = 'XBOX360'
...然后使用适当的PHP来检索计数。
答案 1 :(得分:1)
是的,这是太多的查询,太多的开销,以及太多繁重的工作来获得你想要的结果集。
您可以使用单个语句从$tbl_players
表中获取所有这九个计数,并在一行中。您拥有的这九个单独的语句正在准备九个单独的结果集,并且您将结果集中的所有这些行提取给客户端以获取计数。 (也许在那里有一些优化,但是MySQL正在准备所有那些行返回到客户端。)让MySQL只返回你想要的计数会更有效率,使用类似这样的语句:
SELECT SUM(IF(p.Console = 'XBOX360' ,1,0)) AS xbox
, SUM(IF(p.Console = 'PS3' ,1,0)) AS ps3
, SUM(IF(p.Console = 'PC' ,1,0)) AS pc
, SUM(IF(p.Console = 'XBOX360' AND p.fathread LIKE 'http%' ,1,0)) AS xbfa
, SUM(IF(p.Console = 'PS3' AND p.fathread LIKE 'http%' ,1,0)) AS psfa
, SUM(IF(p.Console = 'PC' AND p.fathread LIKE 'http%' ,1,0)) AS pfa
, SUM(IF(p.Console = 'XBOX360' AND p.crthread LIKE 'http%' ,1,0)) AS xbfr
, SUM(IF(p.Console = 'PS3' AND p.crthread LIKE 'http%' ,1,0)) AS pscr
, SUM(IF(p.Console = 'PC' AND p.crthread LIKE 'http%' ,1,0)) AS pcr
FROM $tbl_players p
这会让你回到一行,有九个值。这将大大减少您获得的代码量,并显着提高性能。
同样,您也可以使用单个语句从$tbl_interactive
表中获取所有这些计数:
SELECT SUM(IF(t.Console = 'XBOX360' AND t.Type = 'Player' ,1,0)) AS xbfi
, SUM(IF(t.Console = 'XBOX360' AND t.Type = 'Club' ,1,0)) AS xbci
, SUM(IF(t.Console = 'PS3' AND t.Type = 'Player' ,1,0)) AS psfi
, SUM(IF(t.Console = 'PS3' AND t.Type = 'Club' ,1,0)) AS psci
, SUM(IF(t.Console = 'PC' AND t.Type = 'Player' ,1,0)) AS pcfi
, SUM(IF(t.Console = 'PC' AND t.Type = 'Club' ,1,0)) AS pcci
FROM $tbl_interactive t
WHERE t.Console IN ('XBOX360','PS3','PC')
AND t.Type IN ('Player','Club')
AND $date < t.EndTime
while($row = mysql_fetch_array($tbl_interactive_counts))
{
$xboxfi = $row["xbfi"];
$xboxci = $row["xbci"];
$ps3fi = $row["psfi"];
$ps3ci = $row["psci"];
$pcfi = $row["pcfi"];
$pcci = $row["pcci"];
}
当没有满足谓词的行(即匹配WHERE子句)时,上面的SQL语句可能返回NULL
而不是零。要使语句返回零计数而不是NULL,我们可以使用MySQL IFNULL()
函数作为方便的简写:
SELECT IFNULL(SUM(IF(t.Console = 'XBOX360' AND t.Type = 'Player' ,1,0)),0) AS xbfi
, IFNULL(SUM(IF(t.Console = 'XBOX360' AND t.Type = 'Club' ,1,0)),0) AS xbci
, IFNULL(SUM(IF(t.Console = 'PS3' AND t.Type = 'Player' ,1,0)),0) AS psfi
, IFNULL(SUM(IF(t.Console = 'PS3' AND t.Type = 'Club' ,1,0)),0) AS psci
, IFNULL(SUM(IF(t.Console = 'PC' AND t.Type = 'Player' ,1,0)),0) AS pcfi
, IFNULL(SUM(IF(t.Console = 'PC' AND t.Type = 'Club' ,1,0)),0) AS pcci
FROM $tbl_interactive t
WHERE t.Console IN ('XBOX360','PS3','PC')
AND t.Type IN ('Player','Club')
AND $date < t.EndTime
请注意,我们刚刚包装了一个表达式:IFNULL(expr,0)
这只是一个等同于:IF(expr IS NULL, 0, expr)
也等同于ANSI标准:CASE WHEN expr IS NULL THEN 0 ELSE expr END
(使用IFNULL
,我们只需要指定expr
一次。)
或者,你可以让MySQL返回NULL,并在PHP中用零处理NULL的替换。 (请注意,$row
数组中的获取值仍将包含NULL
,但将为标量指定零:
$xboxfi = is_null($row["xbfi"]) ? 0 : $row["xbfi"] ;
答案 2 :(得分:0)
您向服务器发送了9个请求,需要9次往返。为什么不使用单个UNION ALL
和单个请求?对你的程序了解不够,可以肯定地说你可能想考虑一些重新设计。
答案 3 :(得分:0)
根据您在表格中的内容,您可以使用汇总查询来获取所需信息。
SELECT COUNT(*) `total`, Console, fathread
FROM $tbl_players
GROUP BY Console, fathread
答案 4 :(得分:0)
由于您只计算每个类别中的条目数,因此您可以使用COUNT
和GROUP BY
来消除大多数查询。一个例子:
$tbl_players_result = mysql_query("SELECT Console, COUNT(*) AS item_count FROM $tbl_players GROUP BY Console");
while($row = mysql_fetch_assoc($tbl_players_result))
{
/* Testing... */
print($row["Console"] . " - " . $row["item_count"] . " items");
}
对于具有附加条件的查询(fathread,crthread),您可以执行相同的操作。
此外,您只需为每个结果调用mysql_num_rows
一次,因此您也不需要这些while
循环。
答案 5 :(得分:0)
许多CMS系统和在线商店在一次刷新时运行50个或更多查询。
无论如何 - 在你的情况下 - 我看到了一些优化的可能性。例如 - 您可以在一个查询中读取有关许多类型和控制台的信息,然后在PHP中处理/过滤返回的数据。也许你应该在PHP(数组,结果获取,foreach循环)和一些MySQL训练中进行一些简单和中等的练习。它会帮助你很多。我认为大多数节省时间的教育材料都是The New Boston或PHP Academy。有许多有价值的视频教程。
我不会给你完整的解决方案(这可能需要花费太多时间),我不确定你的查询的最终目的是什么,但你可以从将它们合并到一个查询开始。
也许是这样的?
SELECT * FROM $tbl_interactive
WHERE
Console IN('XBOX360', 'PS3', 'PC') &&
Type in('Player','Club') &&
$date < EndTime
如果您只想获得行数 - 您不应该使用*
并在PHP中计算结果集行数。
使用一个字段或计数(*)函数。在某些字段上添加GROUP BY
,并将这些字段添加到结果中(在计数之前或之前)会将您的计数结果划分为包含少量选项的几行,并为您的组添加行数。
以身作则计数和分组:
SELECT Type, Console, count(*) FROM $tbl_interactive
WHERE
Console IN('XBOX360', 'PS3', 'PC') &&
Type in('Player','Club') &&
$date < EndTime
GROUP BY Type, Console
当然你必须阅读结果集,而不是返回的行数。
在MySQL工作台或phpmyadmin中尝试查看它是如何工作的。