Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PDO much slower than mysql query?

Tags:

php

mysql

pdo

I am using a PDO object in PHP to run MYSQL queries, and I have been trying to work on a query to speed it up. The query is as follows, as seen in my PHP file:

$query = 
"SELECT SQL_NO_CACHE f.position, s.item_id, s.item_type, s.title, s.caption, s.date
FROM apiv2.search_all s 
INNER JOIN apiv2.tags t 
USING(item_id, item_type) 
LEFT JOIN apiv2.featured f 
ON t.item_id = f.item_id AND t.item_type = f.item_type AND f.feature_type = :id 
WHERE t.tag = 'FeaturedContent'
ORDER BY position IS NULL, position ASC, date";

$mysql_vars[':id'] = $id;
$stmt = $connection->prepare($query);
$stmt->execute($vars);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);

This query runs significantly differently depending on whether I include the ORDER BY clause, but only at the MYSQL console:

 - MYSQL Console with ORDER BY: 1.07 sec
    - starting  0.000141
    - Opening tables    0.001416
    - System lock   0.000003
    - Table lock    0.000007
    - init  0.000021
    - checking permissions  0.000001
    - checking permissions  0.000036
    - optimizing    0.000027
    - statistics    0.000027
    - preparing 0.000015
    - Creating tmp table    0.003440
    - executing 0.000001
    - Copying to tmp table  1.050029
    - Sorting result    0.013097
    - Sending data  0.000295
    - end   0.000002
    - removing tmp table    0.002045
    - end   0.000003
    - query end 0.000002
    - freeing items 0.000331
    - logging slow query    0.000002
    - cleaning up   0.000007
 - MYSQL Console unordered output: .0053 sec
    - starting  0.000076
    - Opening tables    0.001506
    - System lock   0.000002
    - Table lock    0.000005
    - init  0.000015
    - checking permissions  0.000001
    - checking permissions  0.000022
    - optimizing    0.000012
    - statistics    0.000021
    - preparing 0.000011
    - executing 0.000001
    - Sending data  0.002895
    - end   0.000002
    - query end 0.000001
    - freeing items 0.000078
    - logging slow query    0.000000
    - cleaning up   0.000002
 - PDO Prepared stmt ORDER BY: 1.18 sec
    - 'Status' => 'starting', 'Duration' => '0.000147'
    - 'Status' => 'Opening tables', 'Duration' => '0.000784'
    - 'Status' => 'System lock', 'Duration' => '0.000004'
    - 'Status' => 'Table lock', 'Duration' => '0.000007'
    - 'Status' => 'init', 'Duration' => '0.000017'
    - 'Status' => 'checking permissions', 'Duration' => '0.000002'
    - 'Status' => 'checking permissions', 'Duration' => '0.000028'
    - 'Status' => 'optimizing', 'Duration' => '0.000018'
    - 'Status' => 'statistics', 'Duration' => '0.000026'
    - 'Status' => 'preparing', 'Duration' => '0.000014'
    - 'Status' => 'Creating tmp table', 'Duration' => '0.002112'
    - 'Status' => 'executing', 'Duration' => '0.000001'
    - 'Status' => 'Copying to tmp table', 'Duration' => '1.033056'
    - 'Status' => 'Sorting result', 'Duration' => '0.013759'
    - 'Status' => 'Sending data', 'Duration' => '0.073144'
    - 'Status' => 'end', 'Duration' => '0.000003'
    - 'Status' => 'removing tmp table', 'Duration' => '0.001999'
    - 'Status' => 'end', 'Duration' => '0.000004'
    - 'Status' => 'query end', 'Duration' => '0.000007'
    - 'Status' => 'freeing items', 'Duration' => '0.000118'
    - 'Status' => 'logging slow query', 'Duration' => '0.000001'
    - 'Status' => 'cleaning up', 'Duration' => '0.000003'
 - PDO Prepared stmt unordered output: 1.06 sec
    - 'Status' => 'starting', 'Duration' => '0.000074'
    - 'Status' => 'Opening tables', 'Duration' => '0.001364'
    - 'Status' => 'System lock', 'Duration' => '0.000004'
    - 'Status' => 'Table lock', 'Duration' => '0.000007'
    - 'Status' => 'init', 'Duration' => '0.000017'
    - 'Status' => 'checking permissions', 'Duration' => '0.000001'
    - 'Status' => 'checking permissions', 'Duration' => '0.000026'
    - 'Status' => 'optimizing', 'Duration' => '0.000015'
    - 'Status' => 'statistics', 'Duration' => '0.000027'
    - 'Status' => 'preparing', 'Duration' => '0.000013'
    - 'Status' => 'executing', 'Duration' => '0.000002'
    - 'Status' => 'Sending data', 'Duration' => '1.048216'
    - 'Status' => 'end', 'Duration' => '0.000003'
    - 'Status' => 'query end', 'Duration' => '0.000001'
    - 'Status' => 'freeing items', 'Duration' => '0.000122'
    - 'Status' => 'logging slow query', 'Duration' => '0.000001'
    - 'Status' => 'cleaning up', 'Duration' => '0.000003' 
 - MYSQL functions from PHP unordered: 1.09 sec
    - 'Status' => 'starting', 'Duration' => '0.000109'
    - 'Status' => 'checking permissions', 'Duration' => '0.000002'
    - 'Status' => 'checking permissions', 'Duration' => '0.000001'
    - 'Status' => 'checking permissions', 'Duration' => '0.000004'
    - 'Status' => 'Opening tables', 'Duration' => '0.002101'
    - 'Status' => 'System lock', 'Duration' => '0.000004'
    - 'Status' => 'Table lock', 'Duration' => '0.000009'
    - 'Status' => 'init', 'Duration' => '0.000032'
    - 'Status' => 'checking permissions', 'Duration' => '0.000003'
    - 'Status' => 'checking permissions', 'Duration' => '0.000057'
    - 'Status' => 'optimizing', 'Duration' => '0.000033'
    - 'Status' => 'statistics', 'Duration' => '0.000065'
    - 'Status' => 'preparing', 'Duration' => '0.000032'
    - 'Status' => 'executing', 'Duration' => '0.000005'
    - 'Status' => 'Sending data', 'Duration' => '1.000079'
    - 'Status' => 'end', 'Duration' => '0.000005'
    - 'Status' => 'query end', 'Duration' => '0.000002'
    - 'Status' => 'freeing items', 'Duration' => '0.000300'
    - 'Status' => 'logging slow query', 'Duration' => '0.000001'
    - 'Status' => 'cleaning up', 'Duration' => '0.000007'
 - MYSQL functions from PHP w/ ORDER BY: 1.09 sec
    - 'Status' => 'starting', 'Duration' => '0.000148'
    - 'Status' => 'checking permissions', 'Duration' => '0.000001'
    - 'Status' => 'checking permissions', 'Duration' => '0.000001'
    - 'Status' => 'checking permissions', 'Duration' => '0.000001'
    - 'Status' => 'Opening tables', 'Duration' => '0.000559'
    - 'Status' => 'System lock', 'Duration' => '0.000002'
    - 'Status' => 'Table lock', 'Duration' => '0.000006'
    - 'Status' => 'init', 'Duration' => '0.000019'
    - 'Status' => 'checking permissions', 'Duration' => '0.000001'
    - 'Status' => 'checking permissions', 'Duration' => '0.000030'
    - 'Status' => 'optimizing', 'Duration' => '0.000018'
    - 'Status' => 'statistics', 'Duration' => '0.000025'
    - 'Status' => 'preparing', 'Duration' => '0.000015'
    - 'Status' => 'Creating tmp table', 'Duration' => '0.001828'
    - 'Status' => 'executing', 'Duration' => '0.000001'
    - 'Status' => 'Copying to tmp table', 'Duration' => '0.958071'
    - 'Status' => 'Sorting result', 'Duration' => '0.013502'
    - 'Status' => 'Sending data', 'Duration' => '0.088148'
    - 'Status' => 'end', 'Duration' => '0.000003'
    - 'Status' => 'removing tmp table', 'Duration' => '0.002037'
    - 'Status' => 'end', 'Duration' => '0.000003'
    - 'Status' => 'query end', 'Duration' => '0.000001'
    - 'Status' => 'freeing items', 'Duration' => '0.000112'
    - 'Status' => 'logging slow query', 'Duration' => '0.000001'
    - 'Status' => 'cleaning up', 'Duration' => '0.000004'

EXPLAINS:

WITH ORDERING

|-id-|-select_type-|-table----|-type---|-possible_keys--------|-key-----------------|-key_len-|-ref-------------------------------------|-rows--|-Extra
|-1--|-SIMPLE------|-s--------|-ALL----|-PRIMARY,search_index-|-NULL----------------|-NULL----|-NULL------------------------------------|-92166-|-Using temporary; Using filesort
|-1--|-SIMPLE------|-tags-----|-eq_ref-|-PRIMARY--------------|-PRIMARY-------------|-426-----|-apiv2.s.item_id,apiv2.s.item_type,const-|-1-----|-Using where; Using index
|-1--|-SIMPLE------|-featured-|-ref----|-type_position_index--|-type_position_index-|-62------|-const-----------------------------------|-3-----|-Using index

WITHOUT ORDERING

|-id-|-select_type-|-table----|-type---|-possible_keys--------|-key-----------------|-key_len-|-ref-------------------------------------|-rows--|-Extra
|-1--|-SIMPLE------|-s--------|-ALL----|-PRIMARY,search_index-|-NULL----------------|-NULL----|-NULL------------------------------------|-88346-|-
|-1--|-SIMPLE------|-tags-----|-eq_ref-|-PRIMARY--------------|-PRIMARY-------------|-426-----|-apiv2.s.item_id,apiv2.s.item_type,const-|-1-----|-Using where; Using index
|-1--|-SIMPLE------|-featured-|-ref----|-type_position_index--|-type_position_index-|-62------|-const-----------------------------------|-3-----|-Using index

TABLE: search_all

CREATE TABLE `search_all` (  
  `item_id` varchar(20) NOT NULL DEFAULT '',  
  `item_type` varchar(20) NOT NULL DEFAULT '',  
  `title` varchar(255) DEFAULT NULL,  
  `caption` text,  
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
  PRIMARY KEY (`item_id`,`item_type`),  
  UNIQUE KEY `search_index` (`item_id`,`item_type`,`date`),  
  KEY `date_index` (`date`)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;  


|-id-|-select_type-|-table------|-type-|-possible_keys-|-key--|-key_len-|-ref--|-rows--|-Extra
|-1--|-SIMPLE------|-search_all-|-ALL--|-NULL----------|-NULL-|-NULL----|-NULL-|-74785-|-

TABLE: tags

CREATE TABLE `tags` (  
  `tag` varchar(100) NOT NULL DEFAULT '',  
  `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
  `item_id` varchar(20) NOT NULL DEFAULT '',  
  `item_type` varchar(20) NOT NULL DEFAULT '',  
  PRIMARY KEY (`item_id`,`item_type`,`tag`)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;  


|-id-|-select_type-|-table-|-type--|-possible_keys-|-key-----|-key_len-|-ref--|-rows---|-Extra
|-1--|-SIMPLE------|-tags--|-index-|-NULL----------|-PRIMARY-|-426-----|-NULL-|-197400-|-Using index

TABLE: featured

CREATE TABLE `featured` (  
  `position` int(10) NOT NULL DEFAULT '0',  
  `item_type` varchar(20) NOT NULL DEFAULT '',  
  `item_id` varchar(20) NOT NULL DEFAULT '',  
  `feature_type` varchar(20) NOT NULL DEFAULT '',  
  PRIMARY KEY (`position`,`item_type`,`item_id`,`feature_type`),  
  KEY `type_position_index` (`feature_type`,`position`)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;  


|-id-|-select_type-|-table----|-type--|-possible_keys-|-key-----------------|-key_len-|-ref--|-rows-|-Extra
|-1--|-SIMPLE------|-featured-|-index-|-NULL----------|-type_position_index-|-66------|-NULL-|-13---|-Using index

Why is there no difference between the unordering in the PDO or MSQL from PHP? Is there any way I could make it faster?

like image 221
Ripptor Avatar asked Jun 22 '11 20:06

Ripptor


People also ask

Is PDO slower than MySQLi?

3. Here you can see that PDO is only 1% faster than mysqli.

Is PDO faster than MySQLi?

Basically they show that for SELECT queries using prepared statements MySQLi runs a bit faster. Still it may not be significant depending on your purposes. Keep in mind that PDO by default uses client side prepared statements emulation.

What is the advantage of PDO over Mysqlli?

Both MySQLi and PDO have their advantages: PDO will work on 12 different database systems, whereas MySQLi will only work with MySQL databases. So, if you have to switch your project to use another database, PDO makes the process easy. You only have to change the connection string and a few queries.

Which is the most important advantage of PDO over MySQLi?

Database Support The core advantage of PDO over MySQLi is in its database driver support. At the time of this writing, PDO supports 12 different drivers, opposed to MySQLi, which supports MySQL only.


1 Answers

Unless your order by is for an indexed column and the optimizer thinks its a good idea to use the index an "ORDER BY" will result in a sort which takes significant time and resources for any result set of any size.

The reason the PDO version is taking longer is that your script is consuming rows slower than SQLServer can serve them up, so the Database is waiting for your program. As you are using an interpreted language and an API which does a considerable amount of manipulation of the row result this is only to be expected. This delay "sending data" is much larger (0.75 sec and 1.04 sec) than the overhead from the sort.

Note the slow retrieval is compounded by the order by. In the case of the unordered SQL the rows will be sent as soon as they are selected. In the case of the ordered select all the rows will have been selected and then sorted before the first result row is sent.

like image 200
James Anderson Avatar answered Sep 27 '22 16:09

James Anderson