【发布时间】:2012-09-02 10:05:39
【问题描述】:
我正在通过命令行 PHP 脚本运行 MySQL 查询(使用 mysqlnd 驱动程序上的 PDO 准备查询)。这是一个带有单个左连接的简单查询,每行返回 100 行和 7 个小列。
当我在 MySQL CLI 中运行此查询时(在运行相关 PHP 脚本的同一台机器上),它需要 0.10 秒——即使抛出了 SQL_NO_CACHE 标志。
当我通过 PDO 运行这个准备好的查询时,它需要 9 多秒。这只是 execute() -- 不包括 fetch 调用所花费的时间。
我的查询示例:
SELECT HEX(al.uuid) hexUUID, al.created_on,
IFNULL(al.state, 'ON') actionType, pp.publishers_id publisher_id,
pp.products_id product_id, al.action_id, al.last_updated
FROM ActionAPI.actionLists al
LEFT JOIN ActionAPI.publishers_products pp
ON al.publisher_product_id = pp.id
WHERE (al.test IS NULL OR al.test = 0)
AND (al.created_on >= :since OR al.last_updated >= :since)
ORDER BY created_on ASC
LIMIT :skip, 100;
我不认为查询有问题,考虑到我尝试过的每个本地 MySQL 客户端都几乎立即运行它,但这里有一些解释:
+----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+
| 1 | SIMPLE | al | index | created_on,last_updated | created_on | 8 | NULL | 100 | Using where |
| 1 | SIMPLE | pp | eq_ref | PRIMARY | PRIMARY | 4 | ActionAPI.al.publisher_product_id | 1 | |
+----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+
2 rows in set (0.00 sec)
PDO 到底在做什么,需要 8.9 秒?
编辑: 正如 cmets 中所述,我也编写了一个 mysql_query 版本,它的性能同样很差。然而,删除部分 WHERE 子句使其运行速度与 MySQL 客户端一样快。继续阅读,了解令人难以置信的细节。
【问题讨论】:
-
只是为了好玩,你介意用
mysql_query()运行一次,看看它是否是PDO的东西吗? -
再说一遍,“只是为了好玩。”就是看看是不是PDO的事情。
-
那么我们就知道这不是 PDO 的事情...... 艰难的人群。
-
不,你知道它和 mysql 绑定一样慢,我们知道它严重未优化并且不再维护。使用mysql可能会导致更多的混乱,如果你编程的时间足够长,你就会知道如何隔离问题。
-
您能否尝试逐一删除部分查询(WHERE 子句、ORDER、LIMIT、HEX/ISNULL 结果字段之一),看看是否有区别?