PDO声明比MySQL CLI长400倍

时间:2018-05-16 16:26:25

标签: php mysql pdo

我正在运行一个PDO预处理语句,用于从大约约6k行的表中进行选择。由于具有~5k pIds的WHERE语句,此特定查询最终返回所有行。该表还在pId列上有一个索引。

 reference.onValue.listen((Event event) {
    var value = event.snapshot.value;
    var uuids = value.keys;
    for(var uuid in uuids) {
      var userNames = value[uuid].keys;
      for(var userName in userNames) {
        var images = value[uuid][userName].values;
        var image = images.firstWhere((img) => img[count]== 1);
        print('uuid: $uuid, userName: $userName, url: $image);
      }
    } 
  });

此查询需要4.5秒才能在php中运行,并且在MySQL CLI中运行需要0.01秒。 PHP和MySQL的EXPLAIN语句是相同的,都使用pId上的索引 NOT 。我认为这是因为MySQL知道它返回整个表并且不需要使用索引。

我知道准备好的语句有一些开销,但是我在其他地方运行一个非常相似的查询(不同的表名)并且它没有接近那么长(约.9秒)。有什么想法吗?

PHP版本:5.5

MySql版本:5.6

1 个答案:

答案 0 :(得分:1)

我怀疑缓慢是在获取行,返回的行数,而不是语句中的5000+绑定占位符。 pId IN ( ? , ? , ... , ? )

我的建议是测试只返回一行,提供一个已知存在的值/返回一行,然后提供4999+个已知不存在/不返回行的值。

例如,如果我们知道表中最高的pId值,请使用高于该值的值,为此类语句提供绑定值

 ... pId IN ( ? , ? , ? , ... , ? )

所以结果相当于运行

 ... pId IN ( 99999999 , 99999998 , 99999997 , ... , 42 )

这与我们将要运行的结果相同

 ... pId IN ( 42 )

我们的期望是只返回一行(pId = 42)。

然后将其时间(5000+绑定值返回1行)与返回单行的两个绑定值进行比较

 ... pId IN ( 99999999 , 42 )

看看性能是否存在显着差异。

(还有更多关于5000+绑定值的工作,但我不希望巨大的差异,但应该进行测试。

稍微考虑一下,使用所有现有绑定值设置测试可能更容易,只需在查询末尾添加LIMIT 2即可。 (我不确定MySQL是否对LIMIT 2有一些性能增强。

最好添加AND pId * 10 = 420

之类的条件

目标是提供一大堆绑定值,但只返回一行或两行。

另一个测试是返回一大堆行,但只使用几个绑定值。也许是一个返回5000多行的范围条件。

查询可以是:

 ... pId >= ? AND pId <= ? 

在我们在5000行附近提供的值之间有足够大的范围。

并比较表现。

我的预测(猜测?)是性能与返回的行数相关,而不是绑定值的数量。

我不确定这是否是你问题的答案,但这是我采取的方法来回答这个问题......“导致这个问题的原因是什么,绑定值的数量,或者行返回?“