Vincent de Lau schrieb:
-----Oorspronkelijk bericht-----
Van: [email protected] [mailto:[email protected]]
Verzonden: woensdag 24 februari 2010 18:23
That blog posting is puzzling me, if not to say, I believe it is
misleading.
Hector Virgen schrieb:
Not the most scientific analysis but this guy seems to get better
performance out of PDO:
Any of the PHP APIs are just tiny wrappers on top of the underlying C
libraries. Mapping from the C call to a PHP call is always about about
equally fast no matter how you do the mapping - in ext/mysql, ext/mysqli
or PDO_MYSQL. If you compare equivalent PHP API calls with each other
they should be very, very close together in performance.
I assume the blog posting is comparing apples and oranges, likely
without the blog author being aware of it. For example, PDO is using a
prepared statement emulation by default for MySQL. It could well be that
the blog posting compares a native prepared statement and a non-prepared
statement. Or, the blog posting has been written in 2009, it could be
that for PDO persistent connections had been used whereas for ext/mysqli
non-persistent connections had been used.
Moral is, forget about API performance. There's not much to squeeze out
of how you map the very same underlying C library calls into PHP API
calls. But it can help a lot to use proper API calls for the task.
One thing I think you should keep in mind with this, is that there is a
layer in between which is Zend_Db. Although the bare PHP speed might be
equal, it might well be that the PDO_MYSQL aligns better with the Zend_Db
architecture then ext/mysqli.
Vincent,
that is a good and important point.
Look, I'm no longer a PHP application developer myself. Back in the past
I loved all those abstraction layers so much. Nowadays, I am the test
slave of Andrey Hristov, the only person in the world that knows the C
implementation of mysqlnd inside out. Therefore, I'm tend to look at
things from an implementors and not from a users perspective.
Let's you issue a query "SELECT a FROM test WHERE b = 1 LIMIT :myvalue"
with PDO_MYSQL. By default PDO will use its prepared statement emulation
to map this query into a non-prepared statement. It will do placeholder
substitution and map your PHP call into something like this (pseudo
C-API calls):
mysql_query("SELECT a FROM test WHERE b = 1 LIMIT 2")
No more. OK, I'm omitting some string escape calls because they are
irrelevant for our discussion. On the line you get:
PHP sends query to MySQL --> MySQL runs query
PHP buffers all results <-- MySQL sends result
Now, let's say you do the same with ext/mysqli. First, you need to use
"SELECT a FROM test WHERE b 1 LIMIT ?" because MySQLs prepared statement
syntax is not aware of named parameters. Second, you'll have to do a lot
more steps. Let's look at the pseudo C-API calls again:
stmt = mysql_stmt_init()
mysql_stmt_prepare("SELECT a FROM test WHERE b = 1 LIMIT ?")
mysql_stmt_bind_param(1, 2)
mysql_stmt_execute()
Who will this look on the line?
PHP acquires a statement handler
PHP asks MySQL to prepare the statement --> MySQL checks the SQL
PHP receives OK <-- MySQL tells PHP SQL is OK
PHP binds variables and sends variables --> MySQL runs query
PHP retrieves results <-- MySQL sends results
As you can see, you already got two round trips from the client to the
server versus one above. But there are more differences: buffered versus
unbuffered results. Native prepared statement results are unbuffered by
default. Depending on your code that can make a significant difference.
Now, can you tell that ext/mysqli is less good, less adapted for
Zend_Db? There ain't no clear answer to this. If you do not really need
prepared statements, why do you use it: what is there in "SELECT a FROM
test WHERE b = 1 LIMIT 2" that forces you to use prepared statements?
From a server perspective prepared statements are more complex to
handle. You need internal prepare structures, you need to keep record of
the handles, you get the hassle with people not freeing handles timely
and so on.
Note that I am not saying you must not use prepared statements. Nor am I
saying Zend_Db is broken by design or something.
So, in the above example PDO ended up with a stellar result: 50% less
round trips, if not more due to buffered vs. unbuffered result sets.
Unfortunately, you can find many bug reports on PDO and LIMIT. How come?
The PDO emulation does not know that MySQL wants you to provide a number
after LIMIT. PDO may go for a safe default and do "SELECT a FROM test
WHERE b 1 LIMIT :myvalue" -> "SELECT a FROM test WHERE b 1 LIMIT '2'" -
eeek, no string allowed here. Of course, the workaround is
straightforward and easy: you tell PDO its a number not a string.
Continue searching bug reports and you will learn that there are more
such issues. Am I saying PDO is broken, well, yes, I don't like the
emulation. I hate it. In particular I hate the support for stone-age
MySQL versions in PDO_MYSQL --- calm don't that's my private view, it is
nothing you, as a PHP application developer need to take care of. One
last comment on this: Brian and Lukas have written excellent blog
postings why we neither want PS emulations like PDO nor native prepared
statements in todays web applications. Thing is, no database vendor I am
aware of has a good offering for you.
What is the moral of the story? There is no simple black and white, good
and bad, less or better adopted to Zend_Db. It is really important to
know what happens behing the scene to pick the correct tool and API call.
Yes, I believe the blog author that he has observed the figures he had
posted. But, yes, I believe also that different, cleverer PHP coding may
align figures in a way that performance differences between ext/mysql,
ext/mysqli and PDO_MYSQL become irrelevant.
When benchmarking, keep an eye on:
persistent vs. non-persistent connections
(persistent with and without change_user)
buffered vs. unbuffered result sets
native prepared statement vs. non prepared statements
Ulf
--
Ulf Wendel, MySQL
Sun Microsystems GmbH, Sonnenallee 1, D-85551 Kirchheim-Heimstetten
Geschaeftsfuehrer: Thomas Schroeder, Wolfgang Engels, Dr. Roland Boemer
Vorsitzender des Aufsichtsrates: Martin Haering Muenchen: HRB161028