关于 php:准备好的语句是如何工作的?

关于 php:准备好的语句是如何工作的?

How do prepared statements work?

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

我知道准备好的语句主要提供性能优势,以及一些辅助好处,例如不必手动 SQL 转义输入数据。

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

我在下面有两个 getPrice 函数的实现,它接受一个产品 ID 并返回它的价格。

getPrice_A 在同一脚本执行中的后续调用中重复使用同一 PDOStatement 对象。这是必要的还是推荐的?如果是这样,有没有办法避免在每个模型中的每个 get*() 中重复这个额外的代码?

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

写完所有这些并仔细阅读后,我想 getPrice_B 很好,而 getPrice_A 提供的好处可以忽略不计,这可能值得,也可能不值得额外的复杂性。

不过,我仍然希望听到更博学的人的肯定。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
?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\
"
;


据我了解,如果是相同的语句,准备好的语句将重用生成的 SQL 计划,因此数据库将看到相同的准备好的语句,而不必做工作来弄清楚如何查询数据库。我会说将准备好的语句保存在 Product::getPrice_A 中的额外工作通常不是很有帮助,更多的是因为它可以掩盖代码而不是性能问题。在处理性能时,我认为最好始终关注代码的清晰性,然后当您有表明存在问题的真实统计数据时再关注性能。

我会说"是的,额外的工作是不必要的"(不管它是否真的提高了性能)。另外,我不是一个非常大的数据库专家,但是预编译语句的性能提升是我从其他人那里听到的,它是在数据库级别,而不是代码级别(所以如果代码实际上是在调用参数化语句实际的数据库,然后数据库可以做这些执行计划缓存......虽然取决于数据库,即使没有参数化语句,您也可以获得好处)。

无论如何,如果您真的担心(并看到)数据库性能问题,您应该研究缓存解决方案……我强烈推荐使用 memcached。使用这样的解决方案,您可以缓存查询结果,甚至不会针对您经常访问的内容访问数据库。


推荐阅读