我聽說用MySQL數據庫準備好的語句可以提高速度,如果查詢多次完成,我認爲我在項目中有一個理想的情況。但我跑了一些基準,發現完全相反。我是否使用這些陳述錯誤(不是預備陳述的理想情況),還是他們沒有我想象的那麼快?準備好的聲明沒有速度優勢?
這種情況是比賽結果網格。有多個學校參加多個活動,每個學校都有每個活動的分數。爲了得到一個個別學校的分數的所有事件,它需要一個左一個SQL查詢中的連接,如:
SELECT e.`id`, e.`name`, c.`competing`, c.`raw`, c.`final` FROM `events` e LEFT JOIN `scores` c ON e.`id`=c.`event_id` WHERE c.`school_id`=:school_id;
我寫了兩個PHP測試腳本來對樣本數據(200個事件)上運行,使用本機PDO對象(prepare()
/bindValue()
/與query()
):
EDIT低於建議修改測試(香草查詢需要取回,取不同的ID,並結合循環外的準備)。只給出了一個溫和的速度優勢,現在,預處理語句:
預處理語句:
$start = microtime(true);
$sql = 'SELECT e.`id`, e.`name`, c.`competing`, c.`raw`, c.`final` FROM `events` e LEFT JOIN `scores` c ON e.`id`=c.`event_id` WHERE c.`school_id`=:school_id';
echo $sql."<br />\n";
$stmt = $db->prepare($sql);
$sid = 0;
$stmt->bindParam(':school_id', $sid);
for ($i=0; $i<$max; $i++) {
$sid = rand(1,499);
$stmt->execute();
$rs = $stmt->fetchAll();
}
$delta = bcsub(microtime(true), $start, 4);
echo "<strong>Overall time:</strong> $delta<br />\n";
echo "<strong>Average time:</strong> ".($delta/$max)."<br />\n";
香草查詢:
set_time_limit(15); // Add time for each run
$start = microtime(true);
$sql = 'SELECT e.`id`, e.`name`, c.`competing`, c.`raw`, c.`final` FROM `events` e LEFT JOIN `scores` c ON e.`id`=c.`event_id` WHERE c.`school_id`={$sid}';
echo $sql."<br />\n";
for ($i=0; $i<$max; $i++) {
$sid = rand(1,499);
$stmt = $db->query("SELECT e.`id`, e.`name`, c.`competing`, c.`raw`, c.`final` FROM `events` e LEFT JOIN `scores` c ON e.`id`=c.`event_id` WHERE c.`school_id`={$sid}");
$rs = $stmt->fetchAll();
}
$delta = bcsub(microtime(true), $start, 4);
echo "<strong>Overall time:</strong> $delta<br />\n";
echo "<strong>Average time:</strong> ".($delta/$max)."<br />\n";
我取了同一所學校的活動成績(學校編號#10),並將$max
設置爲10,000,我得到的結果顯示vanilla query快30%(25.72秒比36.79)。我做錯了,還是準確的說準備好的聲明即使在重複的情況下也不會更快?
編輯更新的測試現在得到33.95秒準備與34.10香草。 Huzzah,準備好的陳述更快。但是隻有10,000次迭代只需幾分之一秒。可能是因爲我的查詢不是那麼複雜(Prepared語句爲了他們的優勢緩存分析樹)?還是有更多的優化在這裏呢?
如何使用存儲過程比較?你是否確定你有適當的索引? – 2012-03-22 15:44:57
我不熟悉「存儲」過程;我得看看那個。在'scores'和'events'表有相應的索引('events'具有'id'字段的主要和'scores'作爲'school_id' /'event_id'一個兩列PRIMARY指數) – MidnightLightning 2012-03-22 15:55:00
「存儲過程」很好。另一方面,「準備好的陳述」只是另一種工具。它們會產生一些開銷......但在適當的情況下,它們也可以產生性能遊戲,增加安全性並簡化代碼。這裏有一個很好的鏈接:http://blog.ulf-wendel.de/?p=187#procon – paulsm4 2012-03-22 15:56:23