我听说用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