为什么在PHP中使用PDO的某些类型的准备查询速度慢?

Don*_*ill 23 php mysql performance pdo

当使用SELECT * FROM table WHERE Id IN ( .. )带有prepare()/ execute()的PDO使用超过10000个密钥的查询时,性能会比使用mysqli使用预处理语句或PDO执行相同查询而不使用预准备语句的性能降低约10倍.

更奇怪的细节:

  • 更典型的没有WHERE Id IN( ..)子句的SELECT语句即使使用100K +行也能正常运行. SELECT * FROM table WHERE Id例如很快.

  • 在prepare()/ execute()完成后会发生性能下降 - 它完全在PDOStatement::fetch()或中PDOStatement::fetchAll().MySQL查询执行时间在所有情况下都很小 - 这不是MySQL优化的情况.

  • 使用1K密钥将10K查询拆分为10个查询是高性能的.

  • 使用mysql,mysqli和预准备语句,或PDO没有预处理语句是高性能的.

  • 准备好的PDO在下面的例子中需要大约6秒,而其他PDO需要大约0.5秒.

  • 它以非线性方式变得更糟,你拥有的键越多.试试100K钥匙.

示例代码:

// $imageIds is an array with 10K keys
$keyCount = count($imageIds);
$keys = implode(', ', array_fill(0, $keyCount, '?'));
$query = "SELECT * FROM images WHERE ImageID IN ({$keys})";
$stmt = $dbh->prepare($query);
$stmt->execute($imageIds);
// until now, it's been fast.  fetch() is the slow part
while ($row = $stmt->fetch()) {
    $rows[] = $row;
}
Run Code Online (Sandbox Code Playgroud)

El *_*obo 4

确保您告诉 PDO 该值是整数而不是字符串;如果 PDO 将其作为字符串,那么 MySQL 将必须对值进行类型转换以进行比较。根据具体情况,MySQL 可能会避免使用索引,从而导致速度大幅下降。

我不完全确定这里的行为,但几年前我在 Postgres 上遇到过这个问题......

  • 上次我查看代码时,PDO MySQL 驱动程序总是将参数作为字符串传递。大多数数据类型参数都会被忽略(“PDO::PARAM_LOB”和“PDO::PARAM_NULL”除外)。其他品牌的 RDBMS 的一些其他 PDO 驱动程序需要它们。 (3认同)