views:

301

answers:

4
$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?

+4  A: 

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.

le dorfier
yes indeed it was a huge mistake to put prepared stmt inside the loop but after I put both prepare otside the loop the result is 2.39sec wich is only 3% speed increase Shouldn't be more?
not necessarily. The main saving is from composing a query plan for the query. If it's a trivial SQL statement, there's not much to save. Nothing really gets compiled so there really aren't any cpu cycles to speak of, and if your query is hitting the disk at all (i.e. the data isn't cached) that will quickly swamp any cycle savings - disk accesses are so much slower than cpu cycles.
le dorfier
the db is not that big it's only 42.000, but I was hoping for much more savings. But probably you have wright.
@le dorfier, thank you very much
+13  A: 

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.

Guffa
To be more clear, you should prepare it once, and then bind and execute it a thousand times.
MJB
That's what happens when people fail to understand the concept of invariants in loops :-/
luis.espinal
I put both prepared statements ouside the loop and now I have aprox 2.39 sec and in sol.2 I had 2.45.Is it normal? It is just a 3% improvement.
You should run the tests some times so that the database is "warmed up". The database caches the result, so the second test will use the cached data from the first test, giving it an unfair advantage. Also, you are only measuring the execution time, which doesn't show the load on the database during the execution.
Guffa
I see, so it's not the best test to measure the diff between prep statm and regular query. thank you very much
+1  A: 

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

Romain Hippeau
Like I said, I know it was a big mistake to put them inside the loop, but after I put $con -> prepare() outside I get only 3-5% speed increase. i was expected much more, at least 20-30% speed increese.
Why would you expect such an arbitrary % in speed increase? Performance gains and their measurements do not work that way. That is completely dependent on the data size you are fetching and on the throughput (see my response for a better explanation.)
luis.espinal
To add to that, I think you should expect gains on using prepared statements on the long run and health of your application in the form of less temporary objects created during parsing. Not on raw execution numbers. And since it is seldom known when and a how a query (or any piece of code) will be used over time, it is best practice to make them all prepared statements.
luis.espinal
For sigure i'll use prep stmt, but I was thinking that maybe I was doing something wrong (beside puting prepre inside the loop which definitly was a huge mistake). And yes, my % for speed increase was based on what I readed on other tutorials and not on actual tests. Now I understant that I was expecting too much for this kind of tests.
@Romain Hippeau, thank you very much
+1  A: 
luis.espinal
@uis.espinal, thank you very much