2013-03-14 68 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的方法增加顯示的記錄數量,而無需返回到服務器。