Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP运行查询的时间比MySQL客户端长90倍_Php_Mysql_Pdo - Fatal编程技术网

PHP运行查询的时间比MySQL客户端长90倍

PHP运行查询的时间比MySQL客户端长90倍,php,mysql,pdo,Php,Mysql,Pdo,我正在通过命令行PHP脚本运行一个MySQL查询(在mysqlnd驱动程序上使用PDO准备查询)。这是一个简单的查询,只有一个左连接,每行返回100行和7个小列 当我在MySQL CLI中运行这个查询时(在运行所讨论的PHP脚本的同一台机器上),它需要0.10秒——即使在抛出SQL\u NO\u缓存标志的情况下也是如此 当我通过PDO运行这个查询(prepared)时,它需要9秒多的时间。这只是execute(),不包括fetch调用所需的时间 我的查询示例如下: SELECT HEX(al.u

我正在通过命令行PHP脚本运行一个MySQL查询(在mysqlnd驱动程序上使用PDO准备查询)。这是一个简单的查询,只有一个左连接,每行返回100行和7个小列

当我在MySQL CLI中运行这个查询时(在运行所讨论的PHP脚本的同一台机器上),它需要0.10秒——即使在抛出SQL\u NO\u缓存标志的情况下也是如此

当我通过PDO运行这个查询(prepared)时,它需要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客户端几乎都是立即运行的,我不认为这个查询是错误的,但下面是对kicks的解释:

+----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+
| 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秒


编辑:如评论中所述,我也编写了一个mysql_查询版本,它的性能同样很差。但是,删除WHERE子句的一部分会使其运行速度与MySQL客户端一样快。请继续阅读令人难以置信的详细信息。

PDO使用资源来处理行结果。与解释语言(PHP)相比,您将拥有比MySQL更久的脚本来返回结果。 注意:使用mysql_select_db()或mysqli_select_db()比PDO快得多


要了解有关更快的PHP查询的更多信息,请参阅:

对这个问题给出了一个迟到的更新:

我还没有找到原因,但事实证明,PHP中的解释与CLI中的解释不同。我不确定连接的任何方面是否会导致MySQL选择使用不同的字段作为索引,因为据我所知,这些内容不应该相关;但是遗憾的是,PHP的解释表明没有使用正确的索引,而CLI使用了

在这种(令人困惑的)情况下,解决办法是使用。请参见我的示例中修改后的查询中的“FROM”行:

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 USE INDEX (created_on)
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;

希望这对别人有帮助

我也有同样的问题。当从cli和PHP启动时,相同的查询的行为不同。在cli中解释提到了正确的索引用法,而在PHP中则什么都没有。正如我发现的,问题在于类型转换,在我的例子中是datetime。在我为比较值专门设置了cast类型之后,例如,
where datetime\u column>cast('2014-01-12 12:30:01'作为datetime)
一切都正常。

当您在命令行上连接时,很可能使用了与使用PHP连接时不同的字符集

当您要求它使用索引时,它会这样做,因为字符集足够接近,不会引起问题(猜测?这取决于您对表和列的设置)

尝试在其中使用一些unicode字符,它可能会开始返回不好的结果

确保字符集在连接、表和列上匹配,以获得最佳结果。如果不能做到,连接是最重要的


有更多关于踢踢的信息,你介意用
mysql_query()
运行一次,看看它是否是
PDO
的东西吗?再说一遍,“只是踢踢。”只是看看它是否是PDO的东西。然后我们知道它不是PDO的东西。。。不,你知道它和mysql绑定一样慢,我们知道它严重未优化,不再维护。使用mysql可能会导致更多的混乱,如果你已经编程足够长的时间,你知道如何隔离问题。你能试着一个接一个地删除部分查询(WHERE子句、ORDER、LIMIT、HEX/ISNULL结果字段)并看看这是否会产生影响吗?当然,我希望PDO的运行速度比mysql慢。但是我已经用PHP/MySQL编程多年了,对于这样一个简单的结果集,90倍的查询时间开销远远超过解释语言层所能解释的。这里肯定还有更多的事情。好吧,我想这个想法是,
mysqli
不会有什么坏处,这是对OP评论线程中@Flavious的回应。我猜是你的连接字符类型设置没有加工表或列字符类型。Mysql有时会在由于字符集的差异而认为不能使用索引时使用索引。您如何使用PHP的解释?我在PDO手册中找不到参考资料。您只是手动将“explain”添加到查询的开头,还是有一个PDO::explain函数我找不到?@Benubird:是的,我只是在SELECT前面抛出了一个“explain”,并将结果转储了出来。