准备好的语句不应该更快吗?
$s = explode (" ", microtime());
$s = $s[0]+$s[1];
$con = mysqli_connect ('localhost', 'test', 'pass', 'db') or die('Err');
for ($i=0; $i<1000; $i++) {
$stmt = $con -> prepare( " SELECT MAX(id) AS max_id , MIN(id) AS min_id FROM tb ");
$stmt -> execute();
$stmt->bind_result($M,$m);
$stmt->free_result();
$rand = mt_rand( $m , $M ).'<br/>';
$res = $con -> prepare( " SELECT * FROM tb WHERE id >= ? LIMIT 0,1 ");
$res -> bind_param("s", $rand);
$res -> execute();
$res->free_result();
}
$e = explode (" ", microtime());
$e = $e[0]+$e[1];
echo number_format($e-$s, 4, '.', '');
// and:
$link = mysql_connect ("localhost", "test", "pass") or die ();
mysql_select_db ("db") or die ("Unable to select database".mysql_error());
for ($i=0; $i<1000; $i++) {
$range_result = mysql_query( " SELECT MAX(`id`) AS max_id , MIN(`id`) AS min_id FROM tb ");
$range_row = mysql_fetch_object( $range_result );
$random = mt_rand( $range_row->min_id , $range_row->max_id );
$result = mysql_query( " SELECT * FROM tb WHERE id >= $random LIMIT 0,1 ");
}
精心准备的声明更加安全 而且到处都说它们更快 但在我对上述代码的测试中,我有: - 准备好的语句需要 2.45 秒 - 第二个例子是 5.05 秒
你认为我做错了什么? 我应该使用第二种解决方案还是应该尝试优化准备 stmt?
$s = explode (" ", microtime());
$s = $s[0]+$s[1];
$con = mysqli_connect ('localhost', 'test', 'pass', 'db') or die('Err');
for ($i=0; $i<1000; $i++) {
$stmt = $con -> prepare( " SELECT MAX(id) AS max_id , MIN(id) AS min_id FROM tb ");
$stmt -> execute();
$stmt->bind_result($M,$m);
$stmt->free_result();
$rand = mt_rand( $m , $M ).'<br/>';
$res = $con -> prepare( " SELECT * FROM tb WHERE id >= ? LIMIT 0,1 ");
$res -> bind_param("s", $rand);
$res -> execute();
$res->free_result();
}
$e = explode (" ", microtime());
$e = $e[0]+$e[1];
echo number_format($e-$s, 4, '.', '');
// and:
$link = mysql_connect ("localhost", "test", "pass") or die ();
mysql_select_db ("db") or die ("Unable to select database".mysql_error());
for ($i=0; $i<1000; $i++) {
$range_result = mysql_query( " SELECT MAX(`id`) AS max_id , MIN(`id`) AS min_id FROM tb ");
$range_row = mysql_fetch_object( $range_result );
$random = mt_rand( $range_row->min_id , $range_row->max_id );
$result = mysql_query( " SELECT * FROM tb WHERE id >= $random LIMIT 0,1 ");
}
defenitly prepared statements are much more safer
but also every where it says that they are much faster
BUT in my test on the above code I have:
- 2.45 sec for prepared statements
- 5.05 sec for the secon example
What do you think I'm doing wrong?
Should I use the second solution or I should try to optimize the prep stmt?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你做错的是你准备了一千次声明,并且只运行每个准备好的声明一次。您应该准备一次,然后运行一千次。
What you are doing wrong is that you are preparing the statement a thousand times and only run each prepared statement once. You should prepare it once, and run it a thousand times.
在循环内为单次执行准备语句没有任何好处。你只是增加了开销。对通常使用不同参数重复执行的查询使用准备好的语句。
There's no benefit to preparing a statement inside a loop for a single execution. You're just adding overhead. Use prepared statements for queries you execute repeatedly usually with different parameters.
@silversy -
循环基础知识 101(或普通编码 101):将循环不变代码移出循环。当循环中不包含依赖于循环本身的参数时,为什么要在循环中准备语句呢?
当然,如果你在每次循环迭代中都准备好语句,那么如果你使用准备好的语句,它会很糟糕。您观察到的开销是在最初准备的语句中,而不是在其执行中。
按如下方式重新编写代码,然后重试:
这里需要注意,不过,准备好的语句和未准备的语句之间的差异可以忽略不计随着执行查询和获取数据的计算时间变大。
为了便于说明,从我的@@@中提取一些虚构的数字:
假设查询本身和数据获取需要 0.01 秒(称之为 A)。另外,想象一下准备好的语句背后的代码的构建和执行需要 0.01 秒 (X),而对于未准备的查询则需要 0.05 秒或 5 * 0.01 秒 (Y = 5 * X)。准备好的代码和未准备的代码之间的比例为:
我们假设对于另一个查询,获取时间(由于数据量或网络吞吐量)为 10 秒(1000 * 0.01 秒)。然后比率发生变化,
它们几乎无法区分。我想说的是,是的,准备好的语句更快(并且您应该使用它们),但是您正在实施的测试不一定是找出它或衡量其价值的好方法。您必须考虑其他因素才能真正衡量您从它们中榨取的性能。
@silversy -
Loop basics 101 (or plain coding 101): Move loop-invariant code out of the loops. Why would you prepare the statement in the loop when it takes no parameters that are dependent on the loop itself?
Of course it's going to suck gonads if you use prepared statements if you prepare them with each loop iteration. The overhead you observe is in the statement being initially prepared rather than in its execution.
Re-do your code as follows, and re-try again:
The caveat here, though, is that the difference between a prepared statement and a non-prepared one becomes negligible as the computation time to execute the query and fetch the data becomes large.
Just to pull some fictional numbers out of my @@@ for the sake of illustration:
Say that the query itself and the fetching of the data takes 0.01sec (call this A). Also, imagine that the construction and execution of the code behind a prepared statement takes 0.01sec (X) and for the unprepared query 0.05sec or 5 * 0.01 sec (Y = 5 * X). The ration between the prepared and unprepared code would be :
And let's assume that for another query, the fetching time (due to data volume or network throughput) is 10secs (1000 * 0.01sec). Then the ratio changes
They are pretty much indistinguishable. What I'm trying to say is that yes, prepared statements are faster (and that you should use them), BUT the test you are implementing is not necessarily a good way to find that out or to gauge their value. You have to take other factors into account to really measure the performance you are squeezing out of them.
除了上面的答案之外...
我看到您正在使用 MySQL,下面是关于准备好的语句的链接:
http://dev.mysql.com/tech-resources/ articles/4.1/prepared-statements.html
摘录:
准备好的语句性能的提高可以来自一些不同的功能。首先是只需要解析一次查询。当您最初准备语句时,MySQL 将解析该语句以检查语法并设置要运行的查询。然后,如果您多次执行该查询,则将不再有该开销。如果您需要多次运行相同的查询,这种预解析可以提高速度
In addition to the answers above...
I see you are using MySQL and below is the link from there as to prepared statements:
http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html
An excerpt from there:
The increase in performance in prepared statements can come from a few different features. First is the need to only parse the query a single time. When you initially prepare the statement, MySQL will parse the statement to check the syntax and set up the query to be run. Then if you execute the query many times, it will no longer have that overhead. This pre-parsing can lead to a speed increase if you need to run the same query many times