【问题标题】:Benefiting from PDO Prepared statement when used in a function or method在函数或方法中使用时受益于 PDO Prepared 语句
【发布时间】:2015-07-22 04:11:33
【问题描述】:

每http://php.net/manual/en/pdo.prepared-statements.php

查询只需要解析(或准备)一次,但可以 使用相同或不同的参数多次执行。什么时候 查询准备好,数据库将分析、编译和优化 它执行查询的计划。对于复杂的查询,这个过程可以 占用足够的时间,它会显着减慢应用程序 如果需要以不同的方式多次重复相同的查询 参数。通过使用准备好的语句,应用程序避免了 重复分析/编译/优化循环。这意味着准备 语句使用更少的资源,因此运行速度更快。

因此,在使用准备好的语句时,以下内容将受益于改进的性能:

<?php
...
$stmt=$conn->prepare('SELECT a FROM mytable WHERE x=?');  //I often use globals or similar for $conn
foreach($array as $id){
    $stmt->execute(array($id));
    $data=$stmt->fetchAll(PDO::FETCH_COLUMN);
    ...
}
...
?>

为了消除重复代码,我希望在函数中执行查询。

在这种情况下,我如何从预准备语句的改进性能中受益?

请注意,以下代码没有提供任何效率优势,实际上比不使用预准备语句要慢。

<?php
function getStuff($x)
{
    ...
    $stmt=$conn->prepare('SELECT a FROM mytable WHERE x=?');
    $stmt->execute(array($x));
    $data=$stmt->fetchAll(PDO::FETCH_COLUMN);
    ...
    return $data;    
};

...
foreach($array as $x){
    $data=getStuff($x);
    ...
}
...
?>

【问题讨论】:

  • 做两个函数,一个准备,一个执行。在您的情况下,您每次都准备相同的查询,这不会提高性能。
  • 在你的场景中你根本没有受益。你准备/执行你的查询,然后扔掉让你重新使用查询的语句句柄。
  • Bv202 和马克。同意我的第二种情况没有任何好处,只有我的第一种。在第二种情况下我如何受益?
  • @Bv202 你说Make two functions, one for preparing, one for executing.。意思是我应该在主脚本中调用函数来准备,然后将准备好的语句对象传递给第二个函数来执行?或者可以使用静态变量或其他东西吗?
  • 看看我 4 年前提出的问题,它可能会对你有所帮助 :) stackoverflow.com/questions/6740153/simple-pdo-wrapper

标签: php pdo


【解决方案1】:

我以前用过这个:

function getStuff($x)
{
    global $conn;
    static $stmt;

    if (null === $stmt) {
        $stmt = $conn->prepare('SELECT a FROM mytable WHERE x=?');
    }

如果函数是无状态的,则此方法有效。 例如,将 $conn 变量作为参数是没有意义的:

function getStuff($conn, $x)
{
    static $stmt;

    if (null === $stmt) {
        $stmt = $conn->prepare('SELECT a FROM mytable WHERE x=?');
    }

因为,静态语句不一定属于提供的连接。

无论你怎么做,你都需要使语句在函数中持久存在,或者以其他方式将函数用作工厂并将语句缓存到其他地方。

编辑,测试非 oop 场景:

echo '<pre>';

function do_something()
{
    static $i = 0;

    echo $i . PHP_EOL;

    $i++;
}

do_something();
do_something();
do_something();
do_something();
do_something();

输出:

0
1
2
3
4

【讨论】:

  • 你可以在函数内部声明静态变量(而不是作为类成员)?我从来没有想过要尝试那个:)
  • 感谢 Flosculus。如果您的第二个版本总是通过相同的 $conn,为什么它不能工作?我不,我说我通常使用全局 for $conn,但实际上我使用的是静态单例类(可能效果相同)。
  • @CD001 显然你可以:P
  • 是的 - 我刚刚重新阅读了文档:php.net/manual/en/language.variables.scope.php ...我猜是有道理的,但我已经习惯了创建对象...*Insert "the more you know" meme here*
  • @user1032531 因为有一个连接参数意味着可以提供替代连接实例。但是,该语句(在这种情况下)直接链接到创建它的“第一个”连接。这是错误的,如果您提供不同的连接,第二次将无法正常工作。
猜你喜欢
  • 1970-01-01
  • 2012-03-27
  • 2020-05-06
  • 1970-01-01
  • 2017-03-19
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多