哪种更有效率,为什么:每页一个数据库连接还是每个函数一个数据库连接?

6
我正在开发一个非常依赖 MySQL 数据库的网站,因此有很多查询操作。
这个帖子中,每个人都建议在页面顶部连接到数据库,并在页面底部断开连接。
我想知道什么更有效率,或一般来说最佳实践:每页只建立一个数据库连接,还是根据需要连接?(或者没有通用答案,这要看情况吗?)
另外,我想找出为什么这是最佳实践,从哪个角度看待场景(例如安全性、速度等等...我不知道还有什么其他数据库连接可能会影响的因素?)
我相信此问题曾被问过在这里 - 但不是针对 PHP 的具体情况,因此我没找到它有用。
我的当前做法是为我编写的每个函数连接到 DB,使用mysqli,并在函数结束时断开连接,因为这对我来说更清洁。这样,如果一个页面不调用需要 DB 访问的函数,将永远不会打开连接。但是,可能每次页面加载最多会有约10个连接,具体取决于用户在网站上的操作。现在我认为这可能是一个公平分配资源的方法。如果我理解正确,只能始终打开1个 DB 连接。因此,我假设所有连接请求都将排队等待。因此,如果用户有多个长而复杂的查询,该用户不会阻止所有流量,因为在每个查询之间,其他短查询可以得到处理。但这只是我编造的东西,我不知道是否真的会这样工作...😄
此外,我知道很多开发人员喜欢使用PDO。我选择在开始开发时使用mysqli,并且我没有切换的计划。我希望我的问题对两个库都适用。
谢谢 😊
3个回答

8
通常创建数据库连接的成本很高。这就是为什么大多数人建议只创建一次连接并重复使用,直到执行停止,甚至更长时间,如果数据库客户端库允许的话。
例如,PDO允许创建持久连接,这据说可以提高性能,因为连接将被重用以服务于连续的多个请求。来自http://php.net/manual/en/pdo.connections.php的说明:
“许多Web应用程序将受益于与数据库服务器建立持久连接。持久连接在脚本结束时不会关闭,而是被缓存并在另一个脚本使用相同凭据请求连接时重新使用。持久连接缓存使您避免了每次脚本需要与数据库通信时建立新连接的开销,从而加快了Web应用程序。”

你说“创建数据库连接是非常耗费资源的”……我会把你的陈述当作真实事实,并且开始每个页面只打开一个连接……如果能提供一些关于为什么它“耗费资源”的额外信息,我将不胜感激。 - oliver_siegel
1
你可以将这个问题单独提出来,以便从更多人那里获得意见。数据库会话是复杂的事情:在客户端有网络连接、SQL解析器状态,在服务器上有各种缓冲区。它们都必须为每个会话创建和初始化,并在会话结束后释放。所有这些都需要相当大的时间,尽管对于某些数据库来说需要更多的时间。 - Joni

5
我建议您考虑使用连接工厂模式。这将允许您仅在需要时在函数中调用工厂(避免不必要的连接开销),同时如果您以前已经建立了连接,则可以重用连接(避免反复构建和拆除连接)。
也许可以在您的页面中包含一个connectionFactory.php,或者通过您的加载程序进行提供,就像这样。
class ConnectionFactory{

private static $factory;
public static function getFactory(){
    if (!self::$factory){
        self::$factory = new ConnectionFactory();
        $this->db = null;
    }
    return self::$factory;
}

private $db;

public function getConnection(){
    if (is_null($this->db))
        $this->db = new mysqli('localhost', 'my_user', 'my_password', 'my_db');
        if ($this->db->connect_error){
            throw new Exception("Connect Error ("
                . $this->db->connect_errno
                . ") "
                . $this->db->connect_error
        );
    }
    return $this->db;
}

public function closeConnection(){
   if (! is_null($this->db)){
       $this->db::close();
       $this->db = null;
   }
}

}

接下来,您可以在函数中稍后使用它:

function doStuff(){
try{
    $conn = ConnectionFactory::getFactory()->getConnection();
}catch (Exception $e){

}

这样可以确保如果您根本不使用连接,则永远不会产生开销,如果您使用了连接,则可以利用该连接。

devzone.zend.com表示:“打开的连接(和类似资源)在脚本执行结束时会自动销毁。”

因此,您不必显式关闭连接。但是,出于性能原因,有时可能希望这样做。这将取决于您运行的上下文,并且您需要在查看上下文时自行平衡。

您还可以查看类似的数据库连接的全局或单例?

注意:我没有测试过任何此代码,它只是一个可能工作的示例。;-)


2
每页一个数据库连接还是每个函数一个数据库连接?
每页一个。
为什么这是最佳实践?
速度和常识。
如果我理解正确,总是只能打开1个DB连接。
错了。唯一的限制可以在DB端设置。而且总会有一个连接池。
每页建立一个单独的数据库连接,还是需要时才连接?
什么阻止您只连接一次,但只在需要时连接?如果没有打开的连接,使您的数据库函数自动连接并在存在时重用它。虽然我认为对于“非常MySQL DB驱动”的站点来说不值得麻烦。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接