【问题标题】:Speeding up my queries in PHP加快我在 PHP 中的查询
【发布时间】:2013-07-29 16:34:40
【问题描述】:

我正在努力加快我创建的网页的速度。我知道问题是我在查询中有一个查询。我觉得必须有一种更快的方法来实现相同的结果,但我的想法已经不多了。 (我第一次尝试加载页面需要 45 秒,现在我减少到大约 6 秒)

我想要做的是从表格中提取运行率信息。我需要从运行率表中提取正确的启动率和运行结束率,但最初我所要做的只是工作中心 ID。

我觉得如果桌子设置得更好一点,那么它可能会非常困难,但这是我继承的,因此我有点卡住了。我需要从每个工作中心(大约 15 个)提取一个月的数据,其中每天可能有多达 4-5 次运行......要处理的数据相当多。

这是 PHP 代码:

$qtotalStartup = mysql_query("
    SELECT startup.recordID, startup.date, startup.time, runrate.rate AS temRate, runrate.formID  
        FROM jos_a_inproc_startup startup JOIN jos_a_runrate runrate ON startup.recordID = runrate.recordID 
        WHERE startup.workcenterId = $id AND runrate.rate > 0 AND runrate.formID = 1 AND startup.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)") or die(mysql_error());

$totalStartCtr = mysql_num_rows($qtotalStartup);


if ($totalStartCtr > 0) {
while($rtotalStartup = mysql_fetch_assoc($qtotalStartup)) {

        $hours = 0;
        $goalRate = 0;
        $sumHrRR = 0;
        $startDate = 0;
        $startTime = 0;

        $startupNum = $rtotalStartup['recordID'];
        $goalRate = $rtotalStartup['temRate'];
        $startDate = $rtotalStartup['date'];
        $startTime = $rtotalStartup['time'];    
        $startTime = strtotime($startDate . ' ' . $startTime);


//now that we have all of the startup form info, we can move to the end of run information

//this query will retrieve the correct date, time, and ending run rate for us to use with our calculations.
$qtotalEOR = mysql_query("
    SELECT eor.recordID AS eorRec, eor.date, eor.time, eor.startupid, runrate1.rate AS tempRate, runrate1.formID 
        FROM jos_a_inproc_eor eor JOIN jos_a_runrate runrate1 ON eor.recordID = runrate1.recordID 
        WHERE eor.startupid = $startupNum AND runrate1.rate > 0 AND runrate1.formID = 3") or die(mysql_error());

$totalEORCtr = mysql_num_rows($qtotalEOR);

if ($totalEORCtr > 0) {
while($rtotalEOR = mysql_fetch_assoc($qtotalEOR)) {

//reset the accumulator to 0 so we don't get extra 'bad' data.
$sumHrRR = 0;
$newGoalRate = 0;
$lastestDate = 0;
$latestTime = 0;

            $eorNum = $rtotalEOR['eorRec'];
            $latestDate = $rtotalEOR['date'];
            $latestTime = $rtotalEOR['time'];
            $latestTime = strtotime($latestDate . ' ' . $latestTime);
            $sumHrRR= $rtotalEOR['tempRate'];

任何想法将不胜感激。我知道如果没有更多信息,可能很难理解我想要了解的内容,所以如果您需要了解其他信息,请告诉我。谢谢。

【问题讨论】:

  • PSA: mysql_* 函数是 deprecated in PHP 5.5。不建议编写新代码,因为它会阻止您将来升级。相反,请使用 MySQLiPDObe a better PHP Developer
  • 您是否使用 EXPLAIN 语句直接在 MySQL 中分析了您的查询?你有适当的索引吗?
  • 我没有……我只是在这家公司工作了几个月,我继承了很多“坏”的做法。我才接触 PHP 一个多月,所以请原谅 PHP 的错误……我还是很陌生。
  • 在大多数情况下,如果页面加载速度很慢,那么数据库查询就会出现问题。这里似乎就是这种情况。您可能希望隔离查询语句并在 MySQL Workbench/PHPMyAdmin 中使用 MySQL EXPLAIN:stackoverflow.com/questions/7999833/…
  • 我不完全理解您的代码,但您似乎正在循环 $qtotalStartup 的结果并在该循环内运行 $qtotalEOR。如果这是真的,那是个坏主意。最好使用第一个查询中的值列表运行第二个查询一次。

标签: php sql


【解决方案1】:

可以尝试使用多个JOINS,比如这个:

SELECT startup.recordID, startup.date, startup.time, 
runrate.rate AS temRate, runrate.formID  

-- stuff from second query
eor.recordID AS eorRec, eor.date AS eor_date, 
eor.time AS eor_time, eor.startupid AS eor_startupid, 
runrate1.rate AS eor_tempRate, 
runrate1.formID AS runrate1_formID

FROM jos_a_inproc_startup startup 
JOIN jos_a_runrate runrate ON startup.recordID = runrate.recordID 

-- second query LEFT JOIN
LEFT JOIN jos_a_inproc_eor eor 
    ON eor.startupid = startup.recordID
LEFT JOIN jos_a_runrate runrate1 
    ON eor.recordID = runrate1.recordID 
    AND runrate1.rate > 0 
    AND runrate1.formID = 3

WHERE startup.workcenterId = $id 
    AND runrate.rate > 0 
    AND runrate.formID = 1 
    AND startup.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)

我不知道我是否正确,但我认为您也在 PHP 中对结果进行一些聚合工作。您可以使用sum()avg()GROUP BY 在数据库中执行此操作。在将较小的结果集从数据库传输到服务器时,您将节省一些时间,以及在 PHP 中进行循环和聚合的时间。而且大多数时候使用JOIN 比在循环中使用查询甚至在查询中使用子查询要快得多。

您还应该检查是否在您搜索的列上设置了索引。还可以使用EXPLAIN 检查查询是如何执行的。

【讨论】:

  • 回复有点晚,但谢谢。使用 EXPLAIN 并获取索引就可以了。但为了安全起见并尝试对服务器更加友好,我采纳了您的建议并使用了多个连接。
【解决方案2】:

您可以使用 Mem-Cache 技术使其更快,并尝试使您的查询更简单,您可以..不要检索您在脚本中不使用的值..

【讨论】:

    【解决方案3】:

    您通常处理多少条记录作为输出?桌子有多大?你检查过索引吗?您最近是否分析过它们(重建它们)?

    另外,您是否使用 deflate 将数据发送回浏览器?见:

    http://httpd.apache.org/docs/2.2/mod/mod_deflate.html

    【讨论】:

      【解决方案4】:

      好吧,您可以尝试使用multiple INNER JOINs (see) 并在一个查询中只使用一个查询而不是一个查询,这会极大地影响性能。你可以试试这样的东西,然后稍微调整一下:

      SELECT
          startup.recordID AS startupRecordID,
          startup.date AS startupDate,
          startup.time AS startupTime,
          runrate.rate,
          runrate.formID,
          eor.recordID AS eorRecordID,
          eor.date AS eorDate,
          eor.time AS eorTime,
          eor.startupid AS eorStartupID
      FROM jos_a_inproc_startup startup
          INNER JOIN jos_a_runrate runrate
          ON startup.recordID = runrate.recordID
          INNER JOIN jos_a_inproc_eor eor
          ON startup.recordID = eor.startupid
      WHERE
          startup.workcenterId = $id
          AND runrate.rate > 0
          AND runrate.formID = 1
          AND startup.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-30
        • 2022-01-17
        • 2015-10-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多