2013-02-19 91 views
0

我一直在使用下面的php和sql來爲英國旅客列車提供時間表信息和實時信息。基本上你必須找到相關的時間表,然後加載每個時間表的實時信息,該時間表與今天的列車有關的不同表中。更有效的SQL查詢方式

該查詢花費的時間比真正的想法還要長,並且使用大量的CPU%,這再次不理想。當談到sql編程時,我非常虛弱,所以任何低效的指針都會很好。

這是一個Android應用程序,所以我試圖通過一個呼叫通過HTTP。打印(*)和>用於在另一端分割字符串。

下面是代碼:

<? 

//Connect to the database 
mysql_connect("localhost","XXXX","XXXX") 
or die ("No connection could be made to the OpenRail Database"); 
mysql_select_db("autotrain"); 
//Set todays date from system and get HTTP parameters for the station,time to find trains   and todays locations table. 
$date = date('Y-m-d'); 
$test = $_GET['station']; 
$time = $_GET['time']; 
$table = $_GET['table']; 

//Find the tiploc associated with the station being searched. 
$tiplocQuery = "SELECT tiploc_code FROM allstations WHERE c LIKE '$test';"; 
$tiplocResult =mysql_query($tiplocQuery); 
$tiplocRow = mysql_fetch_assoc($tiplocResult); 

$tiploc=$tiplocRow['tiploc_code']; 
//Now find the timetabled trains for the station where there exists no departure  information. Goes back two hours to account for any late running. 
$timeTableQuery = "SELECT tiplocs.tps_description AS 'C',  locations$table.public_departure, locations$table.id,schedules.stp_indicator 
,schedules.train_uid 
FROM locations$table, tiplocs, schedules_cache, schedules,activations 
WHERE locations$table.id = schedules_cache.id 
AND schedules_cache.id = schedules.id 
AND schedules.id =activations.id 
AND '$date' 
BETWEEN schedules.date_from 
AND schedules.date_to 
AND locations$table.tiploc_code = '$tiploc' 
AND locations$table.real_departure LIKE '0' 
AND locations$table.public_departure NOT LIKE '0' 
AND locations$table.public_departure >='$time'-300 
AND locations$table.public_departure <='$time'+300 
AND schedules.runs_th LIKE '1' 
AND schedules_cache.destination = tiplocs.tiploc 
ORDER BY locations$table.public_departure ASC 
LIMIT 0,30;"; 

$timeTableResult=mysql_query($timeTableQuery); 


while($timeTablerow = mysql_fetch_assoc($timeTableResult)){ 
$output[] = $timeTablerow; 

} 

//Now for each id returned in the timetable, get the locations and departure times so the app may calculate expected arrival times. 
foreach ($output as $value) { 
$id = $value['id']; 
$realTimeQuery ="SELECT  locations$table.id,locations$table.location_order,locations$table.arrival,locations$table.public_arrival, 
locations$table.real_arrival,locations$table.pass,locations$table.departure,locations$ table.public_departure,locations$table.real_departure,locations$table.location_cancelled, 
tiplocs.tps_description FROM locations$table,tiplocs WHERE id =$id AND  locations$table.tiploc_code=tiplocs.tiploc;"; 

$realTimeResult =mysql_query($realTimeQuery); 
while($row3 = mysql_fetch_assoc($realTimeResult)){ 
    $output3[] = $row3; 
} 
print json_encode($output3); 
print("*"); 
unset($output3); 
unset($id); 
} 


print('>'); 
print json_encode($output); 

?> 

非常感謝 馬特

+5

[**請不要在新代碼'mysql_ *'功能**](http://bit.ly/phpmsql)。他們不再被維護[並被正式棄用](https://wiki.php.net/rfc/mysql_deprecation)。看到[**紅框**](http://j.mp/Te9zIL)?學習[*準備的語句*](http://j.mp/T9hLWi),並使用[PDO](http://php.net/pdo)或[MySQLi](http://php.net/ mysqli) - [這篇文章](http://j.mp/QEx8IB)將幫助你決定哪個。如果你選擇PDO,[這裏是一個很好的教程](http://j.mp/PoWehJ)。 – 2013-02-19 01:29:33

+0

噢,好吧,謝謝你的鏈接。我會改變我做這件事的方式。儘管如此,SQL的問題,並導致減緩任何指導,會遇到很多謝謝。 – 2013-02-19 01:33:42

+0

@Matt:首先研究如何改變你的代碼庫(使用PDO或MySQLi),實施這個改變,然後回來給我們帶來與該代碼有關的特定問題。這真的不是投機性的一般建議或指導的地方。 – 2013-02-19 01:35:18

回答

0

你的設置最大的問題是這個foreach循環,因爲它是不必要的,並導致n次往返數據庫執行查詢,獲取和分析結果。

foreach ($output as $value) { 

重寫初始查詢以包含所有後續計算所需的字段。

這樣的事情會起作用。

SELECT tl.tps_description AS 'C', lc.public_departure, lc.id, s.stp_indicator, s.train_uid, 
lc.id, lc.location_order, lc.arrival, lc.public_arrival, lc.real_arrival, lc.pass, lc.departure, lc.real_departure, lc.location_cancelled 
FROM locations$table lc INNER JOIN schedules_cache sc ON lc.id = sc.id 
    INNER JOIN schedules s ON s.id = sc.id 
    INNER JOIN activations a ON s.id = a.id 
    INNER JOIN tiplocs tl ON sc.destination = tl.tiploc 
WHERE '$date' BETWEEN schedules.date_from AND schedules.date_to 
    AND lc.tiploc_code = '$tiploc' 
    AND lc.real_departure LIKE '0' 
    AND lc.public_departure NOT LIKE '0' 
    AND lc.public_departure >='$time'-300 
    AND lc.public_departure <='$time'+300 
    AND s.runs_th LIKE '1' 
ORDER BY lc.public_departure ASC 
LIMIT 0,30; 

從頁面加載中消除n個查詢執行應該會顯着增加響應時間。

+1

我想upvote獲得有用的答案,但希望downvote延續SQL注入漏洞。 – gazarsgo 2013-02-19 03:20:45

+0

編輯答案,以消除SQL注入漏洞(我不是一個PHP開發人員) – Tahbaza 2013-02-19 03:22:16

0

幾件事我注意到了。

首先,要加入的表在WHERE子句中,像這樣的

from table1, table2 
where table1.something - table2.something 

在FROM子句中加入更快

from table1 join table2 on table1.something - table2.something 

接下來,我不是一個PHP程序員,但它看起來你正在循環內運行類似的查詢。如果這是真的,尋找一種方法來運行一個查詢。

編輯從這裏開始

這是響應gazarsgo的,我回來了通過權利要求有關加入在where子句中速度更快。他是對的,我錯了。這就是我所做的。編程語言是ColdFusion:

<cfsetting showdebugoutput="no"> 
<cfscript> 
fromtimes = ArrayNew(1); 
wheretimes = ArrayNew(1); 
</cfscript> 

<cfloop from="1" to="1000" index="idx"> 
<cfquery datasource="burns" name="fromclause" result="fromresult"> 
select count(distinct hscnumber) 
from burns_patient p join burns_case c on p.patientid = c.patientid 
</cfquery> 
<cfset ArrayAppend(fromtimes, fromresult.executiontime)> 

<cfquery datasource="burns" name="whereclause" result="whereresult"> 
select count(distinct hscnumber) 
from burns_patient p, burns_case c 
where p.patientid = c.patientid 
</cfquery> 
<cfset ArrayAppend(wheretimes, whereresult.executiontime)> 
</cfloop> 
<cfdump var="#ArrayAvg(fromtimes)#" metainfo="no" label="from"> 
<cfdump var="#ArrayAvg(wheretimes)#" metainfo="no" label="where"> 

我確實跑了5次。以毫秒爲單位的結果如下。

9.563 9.611 
9.498 9.584 
9.625 9.548 
9.831 9.769 
9.792 9.813 

第一個數字表示加入from子句,第二次加入where子句。第一個數字只有60%的時間更低。如果它的時間百分之百低,就會表明加入from子句的速度更快,但事實並非如此。

+0

請提供像「加入from子句更快」這樣的語句的證明 – gazarsgo 2013-02-19 03:18:20