2013-03-14 65 views
0

我已经拉回了很多信息,因此我的页面在大约22到24秒内加载。有什么我可以做的,以优化我的代码?如何优化大数据集引起的慢查询?

这里是我的代码:

<?php 
$result_rules = $db->query("SELECT source_id, destination_id FROM dbo.rules"); 

while($row_rules = sqlsrv_fetch_array($result_rules)){ 
$result_destination = $db->query("SELECT pk_id, project FROM dbo.destination WHERE pk_id=" . $row_rules['destination_id'] . " ORDER by project ASC"); 
    while($row_destination = sqlsrv_fetch_array($result_destination)){ 
     echo "Destination project: "; 
     echo "<span class='item'>".$row_destination['project']."</span>"; 
     echo "ID: ".$row_rules['destination_id']."<br>"; 
     if ($row_rules['source_id'] == null) { 
      echo "Source ID for Destination ID".$row_rules['destination_id']." is NULL<br>"; 
     } else { 
      $result_source = $db->query("SELECT pk_id, project FROM dbo.source WHERE pk_id=" . $row_rules['source_id'] . " ORDER by project ASC"); 
      while($row_source = sqlsrv_fetch_array($result_source)){  
       echo "Source project: "; 
       echo $row_source['project']; 
       echo " ID: ".$row_rules['source_id']."<br>"; 
      } 
     } 
    } 
} 
?> 

这里是我的表是这样的:

源表:pk_id:INT,项目:VARCHAR(50),特点:VARCHAR(50),里程碑: varchar(50),reviewGroup:varchar(125),groupId:int

规则表:pk_id:int,source_id:int,destination_id:int,login:varchar(50),status:varchar(50),batchId: int,srcPGroupId:int,dstPGroupId:int

目标表:pk_id:int,项目:varchar(50),功能:varchar(50),里程碑:varchar(50),QAAssignedTo:varchar(50),ValidationAssignedTo:varchar(50),优先级:varchar(50), groupId:int

+0

如何你的表索引? – 2013-03-14 17:29:54

+0

使用“JOIN”组合您的两个查询。 – Kermit 2013-03-14 17:34:25

+1

**您需要向我们展示表和索引定义。**诊断慢查询需要全表和索引定义,而不仅仅是描述或释义。也许你的表格定义不好。也许索引没有正确创建。也许你没有一个你认为你做过的那个专栏的索引。没有看到表和索引定义,我们不能说。如果你知道如何做一个'EXPLAIN'或者得到一个执行计划,那就把结果也放在问题中。 – 2013-03-14 17:34:54

回答

0

如果您需要优化查询的帮助,请提供架构的详细信息和解释计划的输出。

运行嵌套循环对性能不利。在这样的嵌套循环内运行查询是非常糟糕的表现。在select中使用'*'也会影响性能(特别是因为您只使用了几列)。

你应该通过优化PHP和合并查询开始:

$result_rules = $db->query(
    "SELECT rule.destination_id, [whatever fields you need from dbo.rules] 
      dest.project AS dest_project, 
      src.project AS src_project, 
      src.pk_id as src_id 
     FROM dbo.rules rule 
     INNER JOIN dbo.destination dest 
      ON dest.pk_id=rule.destination_id 
     LEFT JOIN dbo.source src 
      ON src.pk_id=rule.source_id 
     ORDER BY rule.destination_id, dest.project, src.project"); 

$last_dest=false; 
$last_src=false; 
while($rows = sqlsrv_fetch_array($result)){ 
    if ($row['destination_id']!==$last_dest) { 
     echo "Destination project: "; 
     echo "<span class='item'>".$row['dest_project']."</span>"; 
     echo "ID: ".$row['destination_id']."<br>"; 
     $last_dest=$row['destination_id']; 
    } 
    if (null===$row['src_id']) { 
     ... I'll let you sort out the rest. 
+0

刚刚更改了SELECT *以选择特定的列。这是我的意思,但忘记了。我会尝试一下JOIN,绝对看起来会有很大的帮助。还添加了有关我的表格的信息。 – theintellects 2013-03-14 17:59:42

+0

为什么我们需要检查$ last_dest? – theintellects 2013-03-14 18:36:46

+0

因为您想要在更改时输出“目标项目:”标题。 – symcbean 2013-03-15 09:55:48

0

(pk_id, project)上添加索引,以便它包含对查询重要的所有字段。

0
  1. 确保pk_Id被索引:http://www.w3schools.com/sql/sql_create_index.asp

  2. 而不是使用select *,只返回你所需要的,除非你需要所有这些列。

  3. 我还建议移动你的SQL代码到服务器并调用存储过程。

  4. 如果您的后台是mysql,您可以考虑使用LIMIT:http://php.about.com/od/mysqlcommands/g/Limit_sql.htm

+0

不幸的是,我只能通过只读帐户访问数据库。我需要拉这3个表中的所有行。有没有什么愚蠢的我在我的PHP逻辑,我可能会改善? – theintellects 2013-03-14 17:31:04

+0

步骤#2仍然可以,所以从表格中选择colA,colB,colC而不是从表格中选择*。此外,你可以看到什么缓冲为你的表现:http://www.sitepoint.com/forums/showthread.php?471650-what-are-buffered-queries。 – RandomUs1r 2013-03-14 17:43:59

+0

我刚刚更新以选择特定的列。我会看看缓冲。 – theintellects 2013-03-14 17:53:56

0

我假设else子句是什么会减慢你的代码。我建议在开始时保存所有你需要的数据,然后在else子句中再次访问数组。基本上,你不需要每次都运行它。

$result_destination = $db->query("SELECT * FROM dbo.destination WHERE pk_id=" . $row_rules['destination_id'] . " ORDER by project ASC") 

您可以更早地获取数据并使用PHP对其进行迭代。

$result_destinations = $db->query("SELECT * FROM dbo.destination ORDER by project ASC") 

然后在您的代码中使用PHP来确定正确的目的地。根据你在做什么,它应该减少一些时间。

0

对于初学者,您希望降低运行的查询数量。例如,做一个查询,遍历这些结果并运行另一个查询,然后遍历该结果集运行更多查询通常被认为是不好的。查询运行的次数呈指数级增长。

例如,如果您有100行从第一个查询返回,并且每个子查询有10个行。第一个查询返回循环的100行。对于您再次查询的每个人。您现在处于101个查询。然后,对于这100个中的每一个,运行另一个查询,每个查询返回10行。您现在处于1001个查询。每个查询都必须将数据发送到服务器(查询文本),等待响应并返回数据。这需要很长时间。

使用连接对所有表执行单个查询并遍历单个结果。

0

另一个考虑因素是浏览器渲染由您的php代码生成的html所花费的时间。您提交的数据越多,所需时间就越长。根据观众的要求,您可能一次只显示x条记录。

有jQuery的方法增加显示的记录数量,而无需返回到服务器。