【问题标题】:PHP: What's the fastest way to query MySQL? Because PDO is painfully slowPHP:查询 MySQL 的最快方法是什么?因为 PDO 非常缓慢
【发布时间】:2011-04-08 03:35:02
【问题描述】:

我需要执行一个简单的查询。

从字面上看,我需要做的就是:

SELECT price, sqft, zipcode FROM homes WHERE home_id = X

当我使用 PHP PDO 时,我已经读过这是连接到 MySQL 数据库的推荐方法,只需创建连接就需要 610ms。。 p>

我的代码如下:

try {
    $conn_str = DB . ':host=' . DB_HOST . ';dbname=' . DB_NAME;
    $dbh = new PDO($conn_str, DB_USERNAME, DB_PASSWORD);
    $params = array();    
    $sql = 'SELECT price, sqft, zipcode FROM homes WHERE home_id = :home_id';
    $params[':home_id'] = X;
    $stmt = $dbh->prepare($sql);    
    $stmt->execute($params);
    $result_set = $stmt->fetchAll(PDO::FETCH_ASSOC);
    // json output  
    ob_start("ob_gzhandler");
    header('Content-type: text/javascript; charset=utf-8');
    print "{'homes' : ";
    print json_encode( $result_set );
    print '}';
    ob_end_flush();
    $dbh = null;
} catch (PDOException $e) {
    die('Unable to connect');
}

问题:连接到我的 MySQL 数据库以执行上述查询的最快方法是什么?

【问题讨论】:

  • 你在 home_id 中设置了索引吗?你是通过 localhost 连接的吗?尝试使用 mysql_* 或 mysqli_*(即 mysqli_connect、mysqli_query 等)
  • 是的,我在 home_id 上有一个索引。我的 Web 服务器与我的 MySQL 数据库服务器位于不同的物理服务器上
  • 这是你问题的主要原因。您可以尝试将数据缓存在会话/存储文件中。
  • @user434493:如果您的 Web 服务器与 MySQL 数据库位于不同的物理机器上,那么网络延迟很可能是罪魁祸首,即使它们在同一个房间中彼此相邻.
  • 你确定是库问题,而不是特定的服务器问题?

标签: php mysql performance pdo


【解决方案1】:

最快:

mysqli_connect("servername", "user", "pass") or die("can't connect");
mysqli_select_db("dbname") or die("can't select database");

list($price, $sqft, $zipcode) = mysqli_fetch_array(mysqli_query("SELECT price, sqft, zipcode FROM homes WHERE home_id = ".mysqli_real_escape_string($home_id)));

[编辑]:现在使用 mysqli 代替 mysql。

【讨论】:

  • 那么原生mysql_库比PDO快吗?
  • @user434493,是的。抽象越少,它变得越快。
  • 你上面的代码不会让我接受 SQL 注入吗?这是使用 PDO 的主要好处之一,它可以保护您免受 SQL 查询字符串的安全攻击
  • 另外,PDO 提供 PREPARED STATEMENTS 而 mysqli_connect 没有。这不是让 PDO 更快吗?
  • mysqli 速度很快,是 php.net 手册建议使用的版本(介于:mysql 和 mysqli 之间)。如果我错了,我希望有人能纠正,PDO的主要优点是它可以连接到所有类型的数据库而不仅仅是mysql。
【解决方案2】:

如果缓慢是由于每个连接都必须通过网络进行,并且 mysql 必须进行反向 DNS 查找以检查其 GRANTs 表,那么这种开销很可能会导致很大一部分延迟。切换到持久连接将使其成为连接生命周期的一次性成本。

但是,这确实会导致其他问题。由于事务会回滚并在持有它们的连接关闭时释放锁,因此持久化意味着它们将保持活动状态。如果您的代码不小心不要让连接处于不一致的状态,您很可能会造成死锁或至少锁定所有其他连接,直到您手动进入并清理。

【讨论】:

  • 关于持久连接的有用阅读:mysqlperformanceblog.com/2006/11/12/… 和这篇关于 PDO 的文章:phpeveryday.com/articles/…
  • @user434493 - 如果您决定使用持久连接来解决网络问题,那么使用 PDO 可能是明智之举。
  • 我遇到一种情况,我正在以百分比形式返回投票结果。我很困惑哪种方法会更快?在查询本身中计算百分比还是在 php 中处理百分比?
【解决方案3】:

从 php 5.3.0 版本开始,从 php 调用数据库的最快和最轻量级的方法如下:

本例使用mysql/ext(不是mysqli)并调用存储过程

$conn = mysql_connect("localhost", "user", "pass");
mysql_select_db("db");

$sql = sprintf("call get_user(%d)", 1);

$result = mysql_query($sql);

mysql_free_result($result);
mysql_close($conn);

存储过程:

delimiter #
create procedure get_user
(
in p_user_id int unsigned
)
begin
    select 
     u.user_id, u.username, u.status_id, s.name as status_name, ...
    from 
        users u
    inner join user_status s on u.status_id = s.status_id
    ...
    where 
      u.user_id = p_user_id;
end #

delimiter ;

【讨论】:

  • 如果您也使用单引号而不是双引号,可能会快一毫秒左右..
  • @IanWarner 单引号和双引号在没有变量时产生相同的 c 代码执行。
  • @Jon Black 嗨,我对存储过程有一个疑问
【解决方案4】:

猜测 PDO 和 MYSQLI 一样快。 我认为您的问题是您如何与 PDO 连接。 可能您的连接字符串如下所示:

:host=localhost;:dbname=foo

问题出在... PDO 尝试连接到 localhost,但 PDO 使用 DNS 将 localhost 转换为 127.0.0.1,这需要时间。 如果你直接使用 127.0.0.1 就不会再有这些问题了 :) 所以连接字符串必须看起来像

:host=127.0.0.1;:dbname=bar

【讨论】:

  • 这对我没有任何影响。我在基于 Linux 的系统上测试了 100 万行样本 - “localhost”和 127.0.0.1 的结果是相同的。
  • @pdolinaj 它不是它自己需要更长时间的语句......它的执行开始。在我的测试中,127.0.0.1localhost 解决方案更早地开始查询数据。
  • 对我来说这个解决方案有效。查询时间从 1 秒减少到 9 毫秒!
猜你喜欢
  • 2013-07-09
  • 2020-09-10
  • 2013-11-06
  • 2011-10-19
  • 2011-09-02
  • 1970-01-01
  • 2016-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多