一尘不染

准备好的语句如何工作?

sql

我正在编写一些数据库例程,并且正在使用准备好的语句。我的环境是使用PHP5的PDO。

我了解到,准备好的语句主要提供了性能上的好处,以及一些附加的好处,例如不必手动进行SQL转义输入数据。

我的问题是关于性能的部分。

我下面有一个getPrice函数的两个实现,该函数采用一个产品ID并返回其价格。

getPrice_A在同一脚本执行中的后续调用之间重用同一PDOStatement对象。这是必需的还是推荐的?如果是这样,有什么方法可以避免在每个模型中的每个get
*()之间重复这些额外的代码?

getPrice_B在每次调用时创建一个新的PDOStatement对象。DBMS是否会认识到该语句已经准备好并且仍然可以跳过某些工作?换句话说,此实现是否适当地利用了预准备语句的性能优势?

写完所有这些并阅读完之后,我想getPrice_B很好,并且getPrice_A在此之上提供的好处微不足道,这可能或可能不值得使您感到额外的麻烦。

我仍然想肯定地从一个更博学的人那里听到。

$pdo在下面的示例中,假定这是一个有效的,已连接的PDO对象。

<?php
class Product {
    static function &getPrice_A($id) {
        static $stmt;
        if (!$stmt) {
            $stmt = $pdo->prepare('SELECT price FROM products WHERE id = ?');
        }
        $stmt->execute(array($id));
        return $stmt->fetchColumn(0);
    }

    static function &getPrice_B($id) {
        $stmt = $pdo->prepare('SELECT price FROM products WHERE id = ?');
        $stmt->execute(array($id));
        return $stmt->fetchColumn(0);
    }
}

// example usage:
$price = Product::getPrice(4982);
echo "Product 4982 costs $price\n";

阅读 185

收藏
2021-05-23

共1个答案

一尘不染

据我了解,如果准备好的语句是同一条语句,则准备好的语句将重用生成的SQL计划,因此数据库将看到相同的准备好的语句,而不必进行工作来弄清楚如何查询数据库。我要说的是,将准备好的语句保存在其中的额外工作Product::getPrice_A通常不是很有帮助,更多是因为它会使代码模糊而不是性能问题。在处理性能时,我觉得始终最好着重于代码的清晰度,然后在具有指示问题的实际统计数据时再关注性能。

我会说“是的,多余的工作是不必要的”(不管它是否真的可以提高性能)。另外,我不是数据库专家,但是我从其他人那里听到了预准备语句的性能提升,这是在数据库级别,而不是代码级别(因此,如果代码实际上是在数据库级别上调用参数化语句)实际的DB,然后DB可以执行这些执行计划缓存。尽管根据数据库的不同,即使没有参数化的语句,您也可能会受益。

无论如何,如果您真的很担心(并看到)数据库性能问题,则应该研究一种缓存解决方案……我强烈建议您使用memcached。使用这种解决方案,您可以缓存查询结果,甚至不用访问频繁访问的内容就可以访问数据库。

2021-05-23