mysqli 或 PDO - 有什么优点和缺点?[已结束]

mysqli or PDO - what are the pros and cons? [closed]

提问人:Polsonby 提问时间:8/17/2008 最后编辑:Polsonby 更新时间:3/4/2013 访问量:149627

问:

锁定。这个问题及其答案被锁定,因为这个问题偏离了主题,但具有历史意义。它目前不接受新的答案或互动。

在我们的位置上,我们分为使用 mysqli 和 PDO 来处理预准备语句和事务支持等内容。有些项目使用一个,有些使用另一个。我们转向另一个RDBMS的可能性很小。

我更喜欢 PDO,因为它允许为准备好的语句命名参数,而据我所知,mysqli 没有。

当我们整合项目以仅使用一种方法时,选择其中一种作为标准还有其他优点和缺点吗?

php mysql pdo mysqli 数据库-抽象

评论

5赞 ravi404 11/28/2012
本文将帮助您选择要使用哪一个。如果您考虑性能,这可能会帮助您做出选择。

答:

57赞 Theo 8/17/2008 #1

将应用程序从一个数据库移动到另一个数据库并不常见,但迟早您可能会发现自己使用不同的 RDBMS 处理另一个项目。如果您在家使用 PDO,那么在这一点上至少会少学一件事。

除此之外,我发现 PDO API 更直观一些,而且感觉更真正面向对象。mysqli 感觉它只是一个被客观化的过程 API,如果你明白我的意思的话。简而言之,我发现 PDO 更容易使用,但这当然是主观的。

5赞 BlaM 8/20/2008 #2

就我个人而言,我使用 PDO,但我认为这主要是一个偏好问题。

PDO具有一些有助于SQL注入(预准备语句)的功能,但是如果您谨慎使用SQL,也可以使用mysqli来实现。

移动到另一个数据库并不是使用 PDO 的理由。只要您不使用“特殊 SQL 功能”,就可以从一个数据库切换到另一个数据库。但是,一旦您使用例如“SELECT ...LIMIT 1“,你不能转到 MS-SQL,因为它是”SELECT TOP 1 ...”。所以无论如何这都是有问题的。

评论

22赞 Tower 7/7/2009
MySQLi 已准备好语句。
25赞 Brian Warshaw 9/8/2008 #3

我开始使用 PDO,因为在我看来,语句支持更好。我使用的是 ActiveRecord 式的数据访问层,实现动态生成的语句要容易得多。MySQLi 的参数绑定必须在单个函数/方法调用中完成,因此,如果您在运行时之前不知道要绑定多少个参数,则被迫使用(我相信这是正确的函数名称)进行选择。忘记简单的动态结果绑定。call_user_func_array()

最重要的是,我喜欢PDO,因为它是一个非常合理的抽象层次。在完全抽象的系统中使用它很容易,因为你不想编写 SQL,但它也使使用更优化、更纯查询类型的系统或混合和匹配两者变得容易。

评论

2赞 Pim Jager 4/21/2009
结果与动态生成的查询绑定是可能的,我们在应用程序中做到了。然而,这是一个巨大的痛苦。
17赞 Dave Gregory 9/11/2008 #4

PDO是标准,是大多数开发人员期望使用的。mysqli 本质上是针对特定问题的定制解决方案,但它具有其他特定于 DBMS 的库的所有问题。PDO是所有辛勤工作和聪明思维的去处。

-4赞 mike 9/24/2008 #5

有一件事要记住。

Mysqli 不支持 fetch_assoc() 函数,该函数将返回带有表示列名的键的列。当然,可以编写自己的函数来做到这一点,它甚至不是很长,但我真的很难写它(对于非信徒:如果这对你来说似乎很容易,请自己尝试一段时间,不要欺骗:))

评论

4赞 Till 9/24/2008
你试过手册吗?php.net/manual/en/mysqli-result.fetch-assoc.php
2赞 mike 9/24/2008
很久以前就开始实施了,但是是的,我检查了手册。它适用于准备好的语句吗?我怀疑......
2赞 Álvaro González 4/30/2010
实际上,它有一个奇怪的部分支持。您可以在常规查询中获取数组,但不能在参数化查询中获取数组:-!
1赞 Majid Fouladpour 4/19/2012
为什么不删除一个明显错误的答案呢?
2赞 Álvaro González 4/24/2012
@MajidFouladpour - 答案并没有明显错误。它只是缺少一些上下文。Mysqli 完全支持关联数组检索。
3赞 Unlabeled Meat 9/24/2008 #6

PDO具有MySQLi所没有的一点,我真正喜欢的是PDO能够将结果作为指定类类型的对象(例如)返回。MySQLi只会返回一个对象。$pdo->fetchObject('MyClass')fetch_object()stdClass

评论

19赞 Andrioid 9/4/2010
实际上,您可以手动指定一个类:“object mysqli_result::fetch_object ([ string $class_name [, array $params ]] )”。仅当未指定任何内容时,才使用 stdClass。
15赞 Tom 12/15/2008 #7

还有一点要记住:目前(PHP 5.2)PDO库有问题。它充满了奇怪的错误。例如:在变量中存储 a 之前,该变量应该避免大量错误。其中大部分已在 PHP 5.3 中修复,它们将于 2009 年初在 PHP 5.3 中发布,其中可能还有许多其他错误。如果你想要一个稳定的版本,你应该专注于使用 PDO for PHP 6.1,如果你想帮助社区,你应该专注于使用 PDO for PHP 5.3。PDOStatementunset()

评论

2赞 Brian Warshaw 11/11/2009
我认为 PDO 提供的收益值得了解并解决这些错误。PHP本身充满了非常严重的错误,有些我们甚至无法有效地解决,但它提供了许多好处,使我们使用它而不是其他选项。
11赞 NikiC 1/23/2011
嗯,奇怪,我从来没有遇到过PDO的任何错误。我经常使用它。
0赞 Bill Karwin 5/7/2013
Mysqli 也有错误。所有软件都有错误。
243赞 Bite code 12/16/2008 #8

好吧,你可以争论面向对象的方面,准备好的语句,它成为标准的事实,等等。但我知道,大多数时候,说服某人使用杀手级功能效果更好。所以就是这样:

PDO的一个好处是你可以获取数据,将其自动注入到一个对象中。如果你不想使用ORM(因为它只是一个快速脚本),但你确实喜欢对象映射,这真的很酷:

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}

评论

12赞 Andy Fleming 4/15/2011
以上和有区别吗?$mysqliResult->fetch_object("student");
2赞 OZ_ 5/25/2011
@e-satis 不,我使用 PHP。公共字段违反了封装,所以它只是......哈哈:)Google 不使用公共字段,只使用访问器:google-styleguide.googlecode.com/svn/trunk/...AS A BEST PRACTICE
6赞 James P. 6/5/2011
@e-satis:很抱歉跳进来,但如果你想控制变量改变时会发生什么,getter 和 setter 是必要的。否则,你根本无法保证你的对象的内部状态(如果你里面有另一个对象,这尤其是一个问题)。这完全与语言无关。@OZ_:放松一下。个人批评只会让别人处于守势。
2赞 Dan Lugg 7/16/2011
@monadic:同意。在处理核心组件或复杂对象等时,封装当然是一个有效的参数,但是作为记录的表示,否则将是读写关联数组,这是可以接受的。此外,当记录在系统中浮动时,它允许更轻松的类型检查。
15赞 Mattygabe 9/1/2011
@outis我希望我不是这里的少数派,但我不认为应该根据他们对新开发人员的安全性来判断答案。听起来很刺耳,但这是真的。回答 SO 的目的不仅仅是提供复制和粘贴代码,而且还提供理解。确保每个安全漏洞或模式缺陷都包含在示例中并不是回答者的工作,因为让我们面对现实吧,代码被复制到的应用程序本质上与使用相同代码的所有其他应用程序不同。
6赞 Joseph Montanez 4/10/2009 #9

从执行速度的角度来看,MySQLi胜出,但除非你有一个好的包装器使用MySQLi,否则它处理准备好的语句的函数是很糟糕的。

我的错误仍然存在,但如果有人想要它,它就在这里

简而言之,如果您正在寻找速度提升,那么 MySQLi;如果您想要易用性,那么 PDO。

评论

2赞 Julius F 11/28/2009
在速度方面,你能给出基准吗?
8赞 Adam 3/8/2011
乔纳森·罗布森(Jonathen Robson)在 jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks 对两者进行了不错的速度比较。摘要:s - 几乎相等,s - mysqli 对于非预处理语句快 ~2.5%,对于预准备语句,~6.7% 快。鉴于性能损失很小,使用的功能和灵活性通常大于性能损失。insertselectPDO
1赞 jnrbsn 3/24/2012
@Adam 感谢您链接到我的博客!
0赞 Dyin 1/13/2013
@daemonfire300 这是真的,不需要基准。PDO 包装 mysqli 库。如果有人能证明 PDO 比 mysqli 快,我可能会打粉丝。:-D
0赞 Basit 2/2/2013
你@jnrbsn同意亚当所说的话吗?
4赞 Dobb 10/15/2010 #10

在我的基准测试脚本中,每个方法都经过 10000 次测试,并打印每个方法的总时间差。你应该在自己的配置上这样做,我相信结果会有所不同!

这些是我的结果:

  • "SELECT NULL" -> PGO()快 ~ 0.35 秒
  • "SHOW TABLE STATUS" -> mysqli()快 ~ 2.3 秒
  • "SELECT * FROM users" -> mysqli()快 ~ 33 秒

注意:通过对mysqli使用->fetch_row(),列名不会添加到数组中,我在PGO中没有找到这样做的方法。但即使我使用 ->fetch_array() ,mysqli 也比 PGO 稍慢,但仍然比 PGO 快(SELECT NULL 除外)。

评论

17赞 Alix Axel 7/26/2011
什么是PGO?快了 33 秒?!我觉得很难相信......
10赞 Alix Axel 7/26/2011 #11

关于PDO的另一个值得注意的(好的)区别是它的PDO::quote()方法会自动添加括起来的引号,而mysqli::real_escape_string()(和类似方法)则不:

PDO::quote() 在输入字符串周围放置引号(如果需要)和 使用引号转义输入字符串中的特殊字符 适合基础驱动程序的样式。

8赞 Dfranc3373 4/21/2012 #12

如果您的站点/Web 应用程序真正成为现实,PDO 将使扩展变得更加容易,因为您可以每天设置主站和从站连接以在数据库中分配负载,而且 PHP 正朝着将 PDO 作为标准的方向发展。

PDO信息

缩放 Web 应用程序

5赞 Your Common Sense 1/13/2013 #13

编辑的答案。

在对这两个 API 都有一些经验之后,我会说有 2 个阻塞级别的功能使 mysqli 无法与本机预准备语句一起使用。
他们已经在 2 个优秀(但被低估)的答案中被提及:

  1. 将值绑定到任意数量的占位符
  2. 仅以数组形式返回数据

本回答中也提到了两者)

由于某种原因,mysqli 两者都失败了。
如今,它对第二个(get_result)进行了一些改进,但它仅适用于 mysqlnd 安装,这意味着您不能在脚本中依赖此功能。

然而,直到今天,它仍然没有按价值绑定。

所以,只有一个选择:PDO

所有其他原因,例如

  • 命名占位符(这种语法糖被高估了)
  • 支持不同的数据库(实际上没有人使用过它)
  • fetch into object(只是无用的语法糖)
  • 速度差(没有)

并不重要。

同时,这两个 API 都缺少一些真正重要的功能,例如

  • 标识符占位符
  • 复杂数据类型的占位符,使动态绑定不那么费力
  • 更短的应用程序代码。

因此,为了满足现实生活中的需求,必须基于这些 API 之一创建自己的抽象库,实现手动解析的占位符。在这种情况下,我更喜欢mysqli,因为它的抽象程度较低。

评论

0赞 Volkan 5/2/2013
终于有人知道并且不否认生活的事实......