当数据库有大量数据时,如何避免在php中执行时间慢

时间:2016-04-05 10:14:11

标签: php mysql datetime

由于我的数据库有大量数据,我的代码需要花费大量时间才能执行。最初当有5000行时它工作正常,但现在我的数据增加了,加载大约需要2分钟。我的PHP代码是:

$result=$db->query("SELECT DateLastSaved,MDid,FileName FROM InitialLog");

$filesarray=array();
$datearray=array();

while($row3=mysqli_fetch_array($result))
{
    $tobestored=$row3['MDid']."||".$row3['FileName'];

    $key=array_search($tobestored,$filesarray);
    $date=$row3['DateLastSaved'];                


    if(!is_numeric($key))
    {
        $filesarray[]=$tobestored;
       $datearray[]=$date;
    }
    else
    {
        $aryear=date("Y",strtotime($datearray[$key]));
        $armonth=date("m",strtotime($datearray[$key]));
        $arday=date("d",strtotime($datearray[$key]));

        $pryear=date("Y",strtotime($date));
        $prmonth=date("m",strtotime($date));
        $prday=date("d",strtotime($date));

       if($aryear==$pryear && $armonth==$prmonth)
       {
           if($prday>$arday)
           {
               $datearray[$key]=$date;
           }
       }
    }
}

数组在此代码中花费了大量时间。

(来自评论)。我的目的是获取每个MD的所有文件名以及最后保存日期。如果从列表中重复出现一个特定的文件并在1月,2月等等存在,我希望该文件仅从1月开始,也就是最早的月份,也是那个月我想要的那个月的最后一个文件,即if它存在于1月1日,1月2日,1月30日,我想获得1月30日的一个。

4 个答案:

答案 0 :(得分:3)

尝试使用HashMap 在php术语中,它是简单的关联数组。

$key=$row3['MDid']."||".$row3['FileName'];
$date=$row3['DateLastSaved'];                

if(!isset($datearray[$key]))
{
   $datearray[$key]=$date;
}
else
{
...
}

它具有恒定的密钥搜索时间,应该非常适合您尝试解决的任务。

答案 1 :(得分:1)

您可以在查询中使用LIMIT并使用分页获取结果来缩短页面加载时间。因此,所有记录都不会出现在单个结果集中,但这可以通过分页

实现
SELECT DateLastSaved,MDid,FileName FROM InitialLog WHERE FileName NOT LIKE '%Patient Names%' LIMIT $offset $perpage

此处$offset是结果的索引号(page_number * $ perpage),$perpage是您要在单个查询中获取的行数。

答案 2 :(得分:1)

您的说明(在对您的问题的评论中提出)是:

  • 对于每个医生的MDid的每个不同值 - ...
  • 查找表格中包含任何行的第一个月...
  • 然后找到第一个月的最新一行,然后......
  • 在结果集中显示该行。

专业提示:尝试在开始编写代码之前尽可能清楚地制定此类规范。规格越细,清晰度就越重要。这个规格有头发。

让我们将其构建为MySQL查询。首先,您需要找到每个MDid出现的第一个月。此子查询使用LAST_DAY()执行此操作。在此应用程序中,将LAST_DAY(date)视为含义MONTH_AND_YEAR_OF(date)

                      SELECT MDid, MIN(LAST_DAY(DateLastSaved)) FirstMonth
                        FROM InitialLog
                       GROUP BY MDid

这个聚合子查询每个医生产生一行,其中第一个月的最后一天。 (这就是MIN(LAST_DAY(DateLastSaved))所做的。)

专业提示:很多人发现在phpMyAdmin或其他命令行SQL程序中测试子查询很有帮助。

现在让我们在另一个子查询中使用它来查找表中第一个月发生的最新日期。

           SELECT MAX(DateLastSaved) LastInMonth,
                  a.MDid
             FROM InitialLog a
             JOIN (
                           SELECT MDid, MIN(LAST_DAY(DateLastSaved)) FirstMonth
                             FROM InitialLog
                            GROUP BY MDid
                  ) b  ON a.MDid = b.MDid 
                      AND LAST_DAY(a.DateLastSaved) = b.FirstMonth
            GROUP BY a.MDid

这里我们将InitialLog表连接到第一个子查询,使用ON子句消除第一个月内没有InitialLog的所有行(这就是{{1} 1}}确实)。

冷却。这个子查询为我们提供了每个医生在您的规范中的日期。最后,我们必须获取包含LAST_DAY(a.DateLastSaved) = b.FirstMonth以及其他列的原始行。我们已经知道FileNameMDid

这是最终查询。

DateLastSaved

这为每个MDid提供一行。它使用DBMS来实现您的规范,而不是查看表的所有行。如果您的表格上有SELECT orig.DateLastSaved, orig.MDid, orig.FileName FROM InitialLog orig JOIN ( /* that subquery */ ) datechoice ON orig.MDid = datechoice.MDid AND orig.DateLastSaved = datechoice.LastInMonth ORDER BY orig.MDid /* or whatever order you want */ 的索引,那么当您的桌子中有数万名医生和数十年的数据时,此查询可能会非常好地扩展。

总而言之,你的php程序就是这样。现在您可能会猜到为什么它被称为结构化查询语言。

(MDid, DateLastSaved)

答案 3 :(得分:0)

首先我想你会说你想要获得最新的' DateLastSaved'对于每个' MDid'和' FileName'组合

如果是这样,我只需将SQL改为

SELECT concat(MDid, FileName) tobestored, 
       max(DateLastSaved) maxDateLastSaved
FROM InitialLog 
GROUP BY 1

此查询每个' MDid'和' FileName'包含组合值和最近日期的组合。

不再需要遍历所有提取的记录来搜索数组键或比较日期。

我唯一不确定的是这部分

if($aryear==$pryear && $armonth==$prmonth) {
  if($prday>$arday) {
    $datearray[$key]=$date;
  }
}

看起来你想保留旧的' DateLastSaved'如果它来自前一个月或一年。 如果这适用,我对您的查询的更改不会提供您想要的数据。