Php PDO语句比MySQL CLI长400倍
我正在运行一个PDO准备的语句,以便从约6k行的表中进行选择。由于WHERE语句有~5k个PID,这个特定的查询最终返回所有的行。该表在pId列上也有一个索引Php PDO语句比MySQL CLI长400倍,php,mysql,pdo,Php,Mysql,Pdo,我正在运行一个PDO准备的语句,以便从约6k行的表中进行选择。由于WHERE语句有~5k个PID,这个特定的查询最终返回所有的行。该表在pId列上也有一个索引 SELECT * FROM table_a WHERE pId in (?, ? ,? ....) 此查询在php中运行需要4.5秒,在MySQL CLI中运行需要0.01秒。PHP和MySQL的EXPLAIN语句是相同的,都是而不是使用pId上的索引。我认为这是因为MySQL知道它正在返回整个表,并且不需要使用索引 我知道预先准备好的
SELECT * FROM table_a WHERE pId in (?, ? ,? ....)
此查询在php中运行需要4.5秒,在MySQL CLI中运行需要0.01秒。PHP和MySQL的EXPLAIN语句是相同的,都是而不是使用pId上的索引。我认为这是因为MySQL知道它正在返回整个表,并且不需要使用索引
我知道预先准备好的语句会有一些开销,但我在别处运行了一个非常类似的查询(不同的表名),而且不会花那么长的时间(大约9秒)。有什么想法吗
PHP版本:5.5
MySql版本:5.6我怀疑在获取行、返回的行数,而不是语句中的5000多个bind占位符时速度较慢<代码>pId在(?、、…、?)中 我的建议是测试只返回一行,提供一个已知存在/返回行的值,然后提供4999+个已知不存在/不返回行的值 例如,如果我们知道表中的最高pId值,请使用高于该值的值,为这样的语句提供绑定值
... pId IN ( ? , ? , ? , ... , ? )
因此,结果相当于运行
... pId IN ( 99999999 , 99999998 , 99999997 , ... , 42 )
这和我们运行的结果是一样的
... pId IN ( 42 )
我们的期望是只返回一行(pId=42)
然后比较(5000+返回一行的绑定值)与返回一行的两个绑定值的计时
... pId IN ( 99999999 , 42 )
并查看性能是否存在显著差异
(对于5000+个绑定值,还有更多的工作要做,但我不希望有太大的差异,但应该进行测试
仔细想想,使用所有现有的绑定值设置测试可能会更容易,只需在查询的末尾添加
limit2
(我不确定MySQL是否对limit2
有一些性能增强)
最好添加一个条件,如和pId*10=420
目标是提供大量绑定值,但只返回一行或两行
另一个测试是返回整组行,但只使用两个绑定值。可能是返回5000+行的范围条件 查询可以是:
... pId >= ? AND pId <= ?
…pId>=?pId在in
子句中使用的pId
是否来自另一个查询?如果是,您可以使用exists重写PDO必须建立连接才能执行操作。将pooling设置为true,并尝试执行此语句几次。我正在质疑4.5秒内包含了什么。这是m吗仅对execute
进行测量。这包括bindValue
调用的时间吗?prepare
调用的时间吗?这包括bindResult
调用的时间,以及获取和处理行的时间吗?PDO是使用服务器端prepare,还是在客户端使用模拟prepare?为了比较,什么是值在没有bindValue调用的情况下被合并到SQL文本中的时间?另外,当不涉及查询缓存时,CLI的执行时间是多少
然后将其强制转换为INT作为3
。当然它会运行得更快。但您是否也会得到相同的结果?:-)PDO存在一个问题。下面是一个相关的未解决问题:…我明白了-您已经发现了。“是什么导致速度变慢,绑定值的数量还是返回的行的数量?”-两者都是-因此是O(n²)@PaulSpiegel:需要通过一些测试来确认……我的怀疑是绑定值的数量对总运行时间的影响不大。我在这个答案中建议的测试应该指出哪个因素(绑定值的数量,或者返回的行数)实际影响了运行时间。(我假设绑定值是由bindValue
提供的,而不是bindParam
,或者这可能没有什么区别。)我的评论是基于测试的。执行一个愚蠢的测试查询,比如select*from t,其中id在(?,,,,,,)或者1=1 limit$numRows
。从1000个参数开始,限制1000个。然后增加参数的数量。您将看到使用相同的结果集增加获取时间。@PaulSpiegel:并且测试是使用bindValue
而不是bindParam
,对吗?它们是使用exec($params)执行的
。但你认为这有什么关系呢?大部分时间都花在fetch()
或fetchAll()
上。