我正在运行一个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
答案 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行附近提供的值之间有足够大的范围。
并比较表现。
我的预测(猜测?)是性能与返回的行数相关,而不是绑定值的数量。
我不确定这是否是你问题的答案,但这是我采取的方法来回答这个问题......“导致这个问题的原因是什么,绑定值的数量,或者行返回?“