PDO vs. MySQLi: Which Should You Use?

PDO vs. MySQLi: Which Should You Use?

Tutorial Details
  • Language: PHP
  • Version: 5+

When accessing a database in PHP, we have two choices: MySQLi and PDO. So what should you know before choosing one? The differences, database support, stability, and performance concerns will be outlined in this article.


Summary

PDO MySQLi
Database support12 different driversMySQL only
APIOOPOOP + procedural
ConnectionEasyEasy
Named parametersYesNo
Object mappingYesYes
Prepared statements
(client side)
YesNo
PerformanceFastFast
Stored proceduresYesYes

Connection

It’s a cinch to connect to a database with both of these:

// PDO
$pdo = new PDO("mysql:host=localhost;dbname=database", 'username', 'password');

// mysqli, procedural way
$mysqli = mysqli_connect('localhost','username','password','database');

// mysqli, object oriented way
$mysqli = new mysqli('localhost','username','password','database');
	

Please note that these connection objects / resources will be considered to exist through the rest of this tutorial.


API Support

Both PDO and MySQLi offer an object-oriented API, but MySQLi also offers a procedural API – which makes it easier for newcomers to understand. If you are familiar with the native PHP MySQL driver, you will find migration to the procedural MySQLi interface much easier. On the other hand, once you master PDO, you can use it with any database you desire!


Database Support

The core advantage of PDO over MySQLi is in its database driver support. At the time of this writing, PDO supports 12 different drivers, opposed to MySQLi, which supports MySQL only.

To print a list of all the drivers that PDO currently supports, use the following code:

var_dump(PDO::getAvailableDrivers());

What does this mean? Well, in situations when you have to switch your project to use another database, PDO makes the process transparent. So all you’ll have to do is change the connection string and a few queries – if they use any methods which aren’t supported by your new database. With MySQLi, you will need to rewrite every chunk of code – queries included.


Named Parameters

This is another important feature that PDO has; binding parameters is considerably easier than using the numeric binding:

$params = array(':username' => 'test', ':email' => $mail, ':last_login' => time() - 3600);
	
$pdo->prepare('
	SELECT * FROM users
	WHERE username = :username
	AND email = :email
	AND last_login > :last_login');
	
$pdo->execute($params);

…opposed to the MySQLi way:

$query = $mysqli->prepare('
	SELECT * FROM users
	WHERE username = ?
	AND email = ?
	AND last_login > ?');
	
$query->bind_param('sss', 'test', $mail, time() - 3600);
$query->execute();

The question mark parameter binding might seem shorter, but it isn’t nearly as flexible as named parameters, due to the fact that the developer must always keep track of the parameter order; it feels “hacky” in some circumstances.

Unfortunately, MySQLi doesn’t support named parameters.


Object Mapping

Both PDO and MySQLi can map results to objects. This comes in handy if you don’t want to use a custom database abstraction layer, but still want ORM-like behavior. Let’s imagine that we have a User class with some properties, which match field names from a database.

class User {
	public $id;
	public $first_name;
	public $last_name;
	
	public function info()
	{
		return '#'.$this->id.': '.$this->first_name.' '.$this->last_name;
	}
}

Without object mapping, we would need to fill each field’s value (either manually or through the constructor) before we can use the info() method correctly.

This allows us to predefine these properties before the object is even constructed! For isntance:

$query = "SELECT id, first_name, last_name FROM users";
	
// PDO
$result = $pdo->query($query);
$result->setFetchMode(PDO::FETCH_CLASS, 'User');

while ($user = $result->fetch()) {
	echo $user->info()."\n";
}
// MySQLI, procedural way
if ($result = mysqli_query($mysqli, $query)) {
	while ($user = mysqli_fetch_object($result, 'User')) {
		echo $user->info()."\n";
	}
}
// MySQLi, object oriented way
if ($result = $mysqli->query($query)) {
	while ($user = $result->fetch_object('User')) {
		echo $user->info()."\n";
	}
}


Security

Both libraries provide SQL injection security, as long as the developer uses them the way they were intended (read: escaping / parameter binding with prepared statements).

Lets say a hacker is trying to inject some malicious SQL through the ‘username’ HTTP query parameter (GET):

$_GET['username'] = "'; DELETE FROM users; /*"

If we fail to escape this, it will be included in the query “as is” – deleting all rows from the users table (both PDO and mysqli support multiple queries).

// PDO, "manual" escaping
$username = PDO::quote($_GET['username']);

$pdo->query("SELECT * FROM users WHERE username = $username");
		
// mysqli, "manual" escaping
$username = mysqli_real_escape_string($_GET['username']);

$mysqli->query("SELECT * FROM users WHERE username = '$username'");

As you can see, PDO::quote() not only escapes the string, but it also quotes it. On the other side, mysqli_real_escape_string() will only escape the string; you will need to apply the quotes manually.

// PDO, prepared statement
$pdo->prepare('SELECT * FROM users WHERE username = :username');
$pdo->execute(array(':username' => $_GET['username']));

// mysqli, prepared statements
$query = $mysqli->prepare('SELECT * FROM users WHERE username = ?');
$query->bind_param('s', $_GET['username']);
$query->execute();

I recommend that you always use prepared statements with bound queries instead of PDO::quote() and mysqli_real_escape_string().


Performance

While both PDO and MySQLi are quite fast, MySQLi performs insignificantly faster in benchmarks – ~2.5% for non-prepared statements, and ~6.5% for prepared ones. Still, the native MySQL extension is even faster than both of these. So if you truly need to squeeze every last bit of performance, that is one thing you might consider.


Summary

Ultimately, PDO wins this battle with ease. With support for twelve different database drivers (eighteen different databases!) and named parameters, we can ignore the small performance loss, and get used to its API. From a security standpoint, both of them are safe as long as the developer uses them the way they are supposed to be used (read: prepared statements).

So if you’re still working with MySQLi, maybe it’s time for a change!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://gurhan.me @murger

    You’ve listed “MS SQL Server” twice for PDO..

    • webarto
      Author

      Thanks for the notice, will fix.

  • http://timshomepage.net Timothy Warren

    You have MS SQL Server listed twice in the image. Also, the Firebird/Interbase driver for PDO is considered experimental.

  • http://twitter.com/mamunabms Abdullah Al Mamun

    Nice write up.
    One year ago, I’ve switched from procedural php mysql API to PDO.
    Thanks :)

    • webarto
      Author

      Thanks. Nice decision :)

  • Agustin

    Guys… is it wrong on using MySQL on php? why is not listed above?

    • webarto
      Author

      Hi, MySQL is most popular database, mysqli is wrapper for MySQL, “i” means improved. Quote from PHP manual: “If you are using MySQL versions 4.1.3 or later it is strongly recommended that you use the mysqli extension instead.”
      Even better, use PDO. Regardless of that, you are still using MySQL database, but you can switch easily to any listed in article, while with mysqli, you can’t.

      • http://www.keithbluhm.com Keith

        As far as easily switching to other databases, not true. PDO is a *data access* abstraction and not a database abstraction. It only provides a common set of methods to access various database types and does provide functionality for proprietary and/or missing features between different types of databases.

    • http://timshomepage.net Timothy Warren

      The original MySQL driver is considered legacy. And although it isn’t deprecated, I could see it being deprecated in the future. MySQLi has more functionality

      To be honest, I wonder why we have two to begin with…seems like the MySQL driver could have been made into what is currently MySQLi…

      • webarto
        Author

        You are probably right, confusion can occur, but it has been used from the start and I doubt it will ever be removed.

      • Phil Sturgeon

        We have two because the native MySQL driver has been around since PHP was just a toddler.

        The “Improved” driver is a new and improved version. That should have been pretty obvious from the name.

        Why didn’t PHP devs rip I out? Because they care about backwards compatability. So now that you’ve had years to switch they are about to deprecate the MySQL driver in PHP 5.4, then remove it in the next release.

  • Chris Timberlake
    • webarto
      Author

      PDO (PHP Data Objects) is included in PHP since version 5.1, means it is faster (compiled). On the other hand, ADOdb supports different databases, so if you are not using the ones that PDO supports, or support is not better than ADOdb, use ADOdb. Really depends on preferences.

    • http://philsturgeon.co.uk Phil Sturgeon

      1999 called, they want their code back.

  • ThePoster

    This article doesn’t hightligh the basics of both technologies. A comparison is utterly wrong: PDO is not a library, it’s an abstracton layer that still needs a database specific driver in the background. They both intend to do very different things. PDO simply unifies the way a database is accesed by myking a single API.

    It should be emphasized that you can’t just simply switch databases with PDO just because it *may* support different database backends. The question is more: what will be used in the future or has less bugs that might show up in a project that is bigger than an average hobby project (still PDO would be the preferred way in any case, but one needs to know the downsides of both techniques).

  • Goues

    I use dibi (http://dibiphp.com/), it basically does the same. What’s more, the author is from my country so I get documentation and support in my native alnguage as well as a wide community.

  • S Walker

    What’s up with the <wbr> in the code examples of the security section?

    In my opinion, supporting multiple databases is not a big selling point for many people. How many of you actually used more than one database system? And more specifically, how many actually had to switch the database system in any of your projects? By-and-large, once a web app is developed with one RDBMS, it is very rarely migrated to another RDBMS.

    Even if PDO is the best choice for most developers and most sites, this article doesn’t cover why you would want to use mysqli over PDO. The article seems too lopsided without any pro-mysqli content. Both mysqli and PDO can be the best choice depending on the needs of your project and knowing the benefits of each makes for a better informed decision. This article only covers the benefits of PDO and touches on only one benefit of mysqli (performance).

    Fortunately, over the years PDO has caught up to mysqli in functionality and can be a “best option” for more people than ever before; but it’s still not *always* the best option.

    • Simon

      Exactly right. I can’t remember changing databases ever in the last 10 years worth of corporate projects I’ve worked on..

  • Ashraam

    I’m using PDO for a while, and this nice article tells me I’m right !

  • http://andywalpole.me/ Andy Walpole

    I would recommend to any coder to use PDO over MySQLi for the simple reason it is the industry standard.

    It features in the main inbuilt and standalone object relational mapping software such as Doctrine, Propel, Zend, Drupal 7 and CakePHP.

    If there is software that still uses MySQLi then expect it to swap over to PDO in the future

  • peter

    MySQLi or PDO…why are so may tutorials on Nettuts still just using MySQL?

    • http://www.shiftedwork.de/blog Daniel S

      The ol’ mysql_functions are deprecated and should not be used anymore. Many tuts in the www are using the mysql_-functions, because they have no idea to do it right. PDO > all.

  • Enrique

    PDO is the winner, but just for noting another difference: MySQLi supports multiple queries (http://php.net/manual/en/mysqli.multi-query.php).

    • webarto
      Author

      See Security part… “both PDO and mysqli support multiple queries”.

      • Edmar

        I also use PDO. But AFAIK PDO does not support multiple queries in the same server round-trip (multiple result sets, ie, multiple unrelated selects).

        Further, it seems MySQLi already supports asynchronous queries, PDO does not.

  • http://dan.cx/ Daniel15

    How is a procedural interface easier? I’d say the OO interface is a lot easier for beginners to understand compared to the procedural interface.

    • S Walker

      That may or may not be true, depending on each programmer’s background. But I can say with some certainty that it is much easier to convert an existing site which uses mysql (old) to mysqli (procedural) with mostly search and replace; whereas migrating that site to PDO (or mysqli OO) takes quite a bit more work.

  • Eric

    PDO link goes to MySQLi info…

  • https://plus.google.com/u/0/116315904568750288560/posts Rupesh

    Good tutorial

    Between PDO link in the first line is moving to MySQLI link should be replaced with this one :-)
    http://php.net/manual/en/book.pdo.php

  • http://touchwebsitesolutions.com/ zafar

    Both are goods but i will prefer to use MySQLi

    • http://www.sutanaryan.com/ ryscript

      yeah me too here, I prefer to use MySQLi ;)

  • http://ebpearls.com.au/ Bharati

    Thanks for sharing such a helpful information.

    Cheers !!!
    Bharati

  • Kevin te Raa

    I am wondering, who has ever switched databases in the middle of a project? I know I haven’t. Besides, you will have to rewrite a lot of stuff if you want to switch to another database anyway.

  • John G

    While this article compares two alternatives it fails to mention that there are others and depending on the use case and the programmer’s way of working it may well be that neither PDO nor MySQLi are the best choice. However, of those two for me there is no choice. It has to be MySQLi. I don’t do OO programming and probably never will. After 40 years of procedural programming in a large number of languages I’m kind of set in my ways.

  • bah

    removed from rss, my brain feels numb everytime i see nonsense articles from nettuts

    • http://okeowoaderemi.com Okeowo Aderemi

      “if you don’t have nothing nice to say then don’t say nothing”

      • http://www.facebook.com/profile.php?id=1311520144 Steini Pé

        Actually it’s “If you have nothing nice to say then don’t say anything at all” :)

      • lollekatt

        Well…since he was using a negatory statement, it should be “If you don’t have anything nice to say; don’t say anything at all” :_)

  • http://www.kieru.com Rob

    A few months ago I launched a beta-test for an in-house project; a management tool to handle pricing and streamline the design process (changes proofing etc) for all of our printing orders at work. Unfortunately I was using MySQL (not even MySQLi) and had a poor understanding of how JOIN really worked.

    The end result was a significant performance issue with multiple embedded SQL queries. It was horrific.

    Fast-forward to today – I’ve been re-writing the same management system using PDO simplified through a PDO wrapper. The performance increase is ridiculous though I attribute the performance increase more to the use of proper joining than the actual switch to PDO.

    Still… it’s sold me on PDO. And for anyone curious as to the wrapper used it can be viewed here: http://code.google.com/p/php-pdo-wrapper-class/

    • Refaelgold

      thanks , this link really help me to understand the basic term of PDO .

  • http://www.wimbledon-it.co.uk Bjoern Schwabe

    Great article. I have used PDO since the time I started developing in PHP – thats about 5 years ago I think. It was just the time when PHP5 was published and all the real OOP started in PHP. Since then I have told many people who use this mysqli stuff that they should have a look at PDO. This is just another great resource I will forward people to in the future when they start arguing or do not know what PDO is : )

  • Michael Rüfenacht

    @Kevin Do you never reuse code in other projects? Or in different environments? If you have to rewrite a lot of other stuff if you switch database you already made design mistakes. As long as you use few DBMS specific stuff there should be no need for a big refactoring.

  • http://www.gaurishsharma.com Gaurish Sharma

    Found a typo:
    “This allows us to predefine these properties before the object is even constructed! For *isntance:*”

    • webarto
      Author

      Thanks, because I can’t edit article, I’m sure editors will do that soon.

    • lollekatt

      LMFAO… the most irrelevant fecking feedback in the history of mankind.

  • Tlangelani

    Is Sybase not supported?

  • http://pressedweb.com Cory

    PDO 100%. Everyone should be studying/using PDO by now for everything.

    I actually released a couple tutorials on PDO. They’re in no way an authority, but they might help someone and the additional resources are handy.

    http://pressedweb.com/tutorials/pdo-baby-steps/
    http://pressedweb.com/tutorials/pdo-baby-steps-prepared-statements/

    • Dane Gardow

      Thanks for the helpful tutorials, Cody. You got me started with PDO.

  • Wouter J

    I always use PDO. Why?
    – MySQL_* become deprecated
    – MySQLi feels like the community grap the MySQL_* functions, put them inside a class and add some bad prepared statements.
    - PDO feels more OO and has much more features.

  • Sebrina Bennison

    I wouldn’t even worry about deleting them permanently because if I need them in future. I would just move them out-of-sight from dock.

  • Onno Marsman

    The reason PDO is not an option for me is that there is no working num_rows function.
    SELECT FOUND_ROWS() is no real alternative because it should return something different than num_rows when using CALC_FOUND_ROWS for efficient paging.

    So it’s mysqli for me.

    • Mylo

      Good info. I did not know that. That is probably a dealbreaker for me as I use num_rows a lot in my applications. In fact I’m surprised that other developers haven’t noticed this because I would think it would be a commonly needed function, but I’m somewhat of a newb, so I could be wrong…

      • Johan Hultin

        Well, there’s always count() which should behave as num_rows aslong as you know what data will be in the array/object.

    • kevk3v

      $query->rowCount();

  • Samir

    PDO has great security, but I prefer mysqli since it’s faster, easier than PDO, and most api/syntax are quite same with the old mysql extension.

    Nice article though.

  • kalabro

    Thanks! And what about master/slave configuration?

  • http://digitalplace.ru/ Wolverine

    Why all think that PDO will help them if they change DB. MySQL have “LIMIT”, MS SQL doesn’t, etc

    And what’s the point using PDO if you have to rewrite your queries considering those differences?

    If you migrate to the other DB you want to get some features you don’t have with current one, while PDO allows you usage of “crossdatabase”, universal format of queries and if you still don’t have to rewrite any queries.. erm.. Why did you migrate from old DB?

    Thanks.

    • http://digitalplace.ru/ Wolverine

      Anyway, the most people use wrappers over PDO or MySQLi.

      The work content looks the same:

      1. if you use mysqli and migrating on mssql you should change your wrapper and some changes in queries.
      2. if you use PDO with MySQL and migrating on MS SQL you should change your wrapper and some changes in queries too.

  • http://piry.net Piry

    I’ve worked with PDO on several websites and I don’t find it to be as useful or … good as everyone here seems to think.

    I still feel that building a mysqli database abstraction layer is the way to go.
    Make your own class, with your own methods that handle whatever you need.
    Put it in a file, include it and that’s it.

    When you switch to another database (for example a MSSQL database), duplicate the file, use “search and replace” on “mysqli_” and replace with “mssql_”, edit the function that adds LIMIT to your queries and change the include mentioned earlier to point to the new file.
    This can be applied to the other listed databases as well.
    Doesn’t sound like a lot of work to me.

    The only valid argument I can see in using PDO is multiple database support, which shouldn’t matter because:
    - you probably have a plan while developing a website, including a “what am I going to do next” plan, and I’m pretty sure that “durr hurr I’ma change ma database” doesn’t belong there
    - you probably won’t need the other 11 databases supported by PDO. It’s like buying a Veyron to drive 5 km to work everyday instead of a Fiesta

    More features doesn’t mean it’s better.

    So if you only use MySQL, like to make sure your code works awesome and feels comfortable, why use PDO instead of making your own wrapper using the mysqli functions included with php ?
    The binding parameter problem and the object mapping one is already solved by using your custom wrapper, so why not use the native functions so you can get that 3% extra performance ?

    I couldn’t find a real reason to use PDO in my php applications that use MySQL.
    And I can’t find one for those MySQL applications that will be converted to MSSQL later. Or Postgre, Oracle.

    What if I want to use Mongo or MaxDB in my application ?

  • Radu

    PDO has proper support for exceptions.
    PDO supports binding of an entire set of parameters from an associative array ($stmt->exec(param_array)).
    PDO can fetch results in an object.

  • http://www.letsearch.com alex

    I agree with the comments Piri has made above.

    indeed Oracle themselves recommend MySQLi over PDO using mySQL

    I personally find pdo cumbersome and awkward, compared to my own database class using My SQLi

    So what if its specific for mySQLi only. it’s a very good choice. Oracle are improving it actively and regularly.

    Alex

  • Mark

    Hi,

    Great article. I wanted to point out that your PDO example under Named Parameters uses:

    $pdo->prepare(…);
    $pdo->execute(…);

    As far as I know, you mean to capture the result of prepare() and call execute on that (the PDOStatement).

  • http://lunaticneko.com neko

    Eh? In my opinion they’re different things, on different layers. With due respect, the author should spend more time comparing between, like, ADO and PDO or something.

    As a plus to mysqli, I find it easier to convert legacy code, which is what I’m doing right now, from mysql to mysqli than to PDO. And why would you support multiple database systems if your entire company uses only MySQL anyway?

  • http://www.influencemedia.com.au Max Doyle

    Great article, although I agree with Piri and Alex I prefer using MySQL as well

  • Rusty

    Could someone recommend some decent books or supply some quality links to learning PDO?

  • http://uzaklab.com W. Kristianto

    PDO vs. MySQLi? The winner is noSQL

  • http://virtual-mafia.com Karevan

    Thanks for the article. I actually started working around with PHP and MySQL just a few time ago, always using the ancient MySQL extension. Doing nothing so big. And now I am facing that the little I learnt will be declared deprecated soon. Well I would like to know which of the both (PDO or MySQLi) should I pick to continue my learning progress, taking in mind I have no experience or interest in working on any databases except MySQL, and that I am a newbie.

    Some recommendations from people more experienced would be a great help for me.

  • Preabsor

    If you write an article like this or other next please you provide us as PDF download too. :)

  • http://www.solopaquetes.com Agustin Lopez

    Thanks ffor the article. I am having a headache trying to migrate a PHP Server 5.2.X to 5.4.4 and this helps.

  • http://zekenierenberg.me Zeke Nierenberg

    A small quibble with a statement you made: “MySQLi performs insignificantly faster in benchmarks – ~2.5% for non-prepared statements.” Do you mean that the 2.5% performance difference doesn’t matter, or that you’re not confident in the measurement. Significance in statistics means that you are sure the observed difference is *real.* It says nothing about its importance. So, you can have very small, very significant differences. It would be good to know if MySQLi is actually faster.

  • https://www.facebook.com/iso.samuel Sam Iso

    Nice comparison, Dejan Marjanovic.
    I was getting confused with the many database classes out there. After reading so many articles and tutorials on different database classes, including ADODB, I find this article very useful as it has helped me decided to use PDO.

  • Carlos Morales

    Hello, the 6.5% better performance you said you obtained in the case of mysqli vs PDO; what does it represent?

    is 6.5% difference on memory use? cpu? number of connections?

  • http://www.isaacewing.com Isaac Ewing

    wow, great tutorial, thank you for sharing!!

  • http://www.ionehouten.16mb.com Iwan

    Like this… thank you for sharing

  • tareco

    What about http://www.dalmp.com ? it uses pure mysqli plus the ability to use memcache/redis/APC and sqlite3 queue.

    if works only for mysql but offers prepared statements very simple.

  • http://www.ewebvn.com PT

    Thank for nice post, i’m trying to PDO. tks again!