mysqliまたはPDO-長所と短所は何ですか?[閉まっている]


342

私たちの代わりに、mysqliとPDOを使用して、準備されたステートメントやトランザクションサポートなどを分割します。プロジェクトによっては、一方を使用するものと、もう一方を使用するものがあります。私たちが別のRDBMSに移行する現実的な可能性はほとんどありません。

PDOは、準備されたステートメントに名前付きパラメーターを許可するという単一の理由で、MySQLiが許可していない限り、PDOを好みます。

プロジェクトを統合して1つのアプローチのみを使用する場合、標準として他のものを選択することについて他に長所と短所はありますか?


5
この記事は、どちらを使用するかを選択するのに役立ちます。パフォーマンスを考慮する場合、これは選択に役立つ場合があります。
ravi404

3
「建設的ではない」質問に投票してスターを付けた人の数はおかしいです。問題は、スレッド全体が非常に建設的であることです。おそらく、質問が建設的であるかどうかを判断するときに、モデレーターはこれを考慮に入れる必要がありますか?
marlar 2013年

@marlar私はあなたに同意します。これは確かにStackOverflowの最大の問題です。優れた質問/議論は常に締め切られます。
Sliq 2013

回答:


243

まあ、あなたはオブジェクト指向の側面、準備されたステートメント、それが標準になるという事実などで議論することができます。だからそれがあります:

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
上記とには違いがあり$mysqliResult->fetch_object("student");ますか?
アンディフレミング

2
@ e-satisいいえ、PHPを使用しています。パブリックフィールドはカプセル化に違反しているので、AS A BEST PRACTICEそれはただ... lol :) Googleはパブリックフィールドを使用せず、アクセサのみを使用します:google-styleguide.googlecode.com/svn/trunk/…
OZ_

6
@ e-satis:ジャンプして申し訳ありませんが、変数が変更されたときに何が起こるかを制御したい場合は、ゲッターとセッターが必要です。そうしないと、単純にオブジェクトの内部状態を保証できません(内部に別のオブジェクトがある場合、これは特に問題です)。これは完全に言語に依存しません。@OZ_:緩和してください。個人的な批判は、誰かを守備に置くだけです。
ジェームズP.

2
@monadic:そうですね。カプセル化はもちろん、コアコンポーネントや複雑なオブジェクトなどを処理する場合の有効な引数ですが、そうでない場合は読み書き可能なレコードの表現として扱われます。アレイ、これは許容範囲です。さらに、レコードがシステム内をフロートするため、タイプチェックが簡単になります。
Dan Lugg、2011

15
@outis私がここに少数派ではないことを願っていますが、新しい開発者に対する安全性について回答を判断すべきではないと思います。厳しいように聞こえますが、それは本当です。SOに関する回答の目的は、コピーアンドペーストのコードを提供することだけでなく、理解を提供することでもあります。すべてのセキュリティホールまたはパターンの欠陥が例でカバーされることを確認するのは回答者の仕事ではありません。それに直面しよう、コードがコピーされるアプリケーションは、同じコードを使用する他のすべてのアプリケーションと本質的に異なるからです。
Mattygabe、2011

57

あるデータベースから別のデータベースにアプリケーションを移動することはあまり一般的ではありませんが、遅かれ早かれ、別のRDBMSを使用して別のプロジェクトで作業する場合があります。PDOを使い慣れている場合は、その時点で少なくとも1つ学ぶことは少なくなります。

それとは別に、PDO APIの方が少し直感的であり、オブジェクト指向がより真に感じられます。mysqliは、私が何を意味するかを知っている場合、オブジェクト化された単なる手続き型APIのように感じます。要するに、PDOの方が扱いやすいと思いますが、もちろん主観的なものです。


25

私の意見では、ステートメントのサポートの方が優れているため、PDOを使い始めました。私はActiveRecord-esqueデータアクセスレイヤーを使用しており、動的に生成されたステートメントを実装する方がはるかに簡単です。MySQLiのパラメーターのバインドは、単一の関数/メソッド呼び出しで行う必要があるため、ランタイムまでバインドするパラメーターの数がわからない場合はcall_user_func_array()、selects を使用する必要があります(これは正しい関数名です)。 。そして、単純な動的結果バインディングについては忘れてください。

何よりも、PDOは非常に合理的なレベルの抽象化であるため、PDOが好きです。SQLを記述したくない完全に抽象化されたシステムで使用するのは簡単ですが、より最適化された純粋なクエリタイプのシステムを使用したり、2つを組み合わせたりすることも簡単になります。


2
動的に生成されたクエリとの結果バインディングが可能です。アプリケーションで行います。しかし、それは大きな痛みです。
Pim Jager、

17

PDOは標準であり、ほとんどの開発者が使用すると予想されるものです。mysqliは基本的に特定の問題に対する特注のソリューションでしたが、他のDBMS固有のライブラリのすべての問題があります。PDOは、すべてのハードワークと賢い思考が行くところです。


15

ここで、覚えておくべきことが他にあります。今のところ(PHP 5.2)、PDOライブラリはバグあります。奇妙なバグがいっぱいです。たとえばPDOStatement、変数に変数を格納する前に、変数はunset()大量のバグを回避するためのものでなければなりません。これらのほとんどはPHP 5.3で修正されており、2009年の初めにPHP 5.3でリリースされる予定です。PHP5.3には他にも多くのバグが存在する可能性があります。安定したリリースが必要な場合はPDO for PHP 6.1の使用に、コミュニティを支援したい場合はPDO for PHP 5.3の使用に重点を置く必要があります。


2
PDOがもたらす利益は、バグを理解し、回避する価値があると思います。PHP自体には非常に深刻なバグがたくさんあり、効率的に回避できないものもありますが、PHPには他のオプションの代わりに使用する多くの利点があります。
Brian Warshaw

11
うーん、奇妙なことに、私はPDOでバグを経験したことはありません。そして、私はそれをたくさん使います。
NikiC、2011年

Mysqliにもバグがあります。すべてのソフトウェアにバグがあります。
Bill Karwin 2013年

10

PDOについてのもう1つの注目すべき(良い)違いは、PDOのPDO::quote()メソッドが囲み引用符を自動的に追加するのに対し、mysqli::real_escape_string()(および類似のもの)はそうしないことです。

PDO :: quote()は、(必要に応じて)入力文字列を引用符で囲み、基になるドライバーに適した引用スタイルを使用して、入力文字列内の特殊文字をエスケープします。


8

データベースに負荷を分散するためにマスター接続とスレーブ接続を毎日設定できるため、サイト/ウェブアプリが実際に稼働している場合、PDOは非常に簡単にスケーリングできます。さらに、PHPは標準としてPDOへの移行に向かっています。

PDO情報

Webアプリケーションのスケーリング


6

実行速度という点ではMySQLiが優先されますが、MySQLiを使用する優れたラッパーがない限り、準備されたステートメントを処理するその関数はひどいです。

私にはまだバグがありますが、誰かがそれを望んでいるなら、ここにあります。

つまり、速度の向上を求めているのであれば、MySQLiです。使いやすさを求めるなら、PDOをお勧めします。


2
スピードという意味では、ベンチマークを教えてもらえますか?
ジュリアスF

8
Jonathen Robsonがjonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarksで 2つの速度を適切に比較しましたます。要約:inserts-ほぼ等しい、selects-mysqliは、準備されていないステートメントの場合は最大2.5%高速、準備されたステートメントの場合は最大6.7%高速です。パフォーマンスのペナルティがどれだけ小さいかを考えると、使用する機能と柔軟性はPDO一般にパフォーマンスへの影響を上回ります。
アダム

1
@アダム私のブログへのリンクをありがとう!
jnrbsn 2012年

@ daemonfire300これは真実であり、ベンチマークの必要はありません。PDOはmysqliライブラリをラップします。PDOがmysqliより速いことを誰かが証明できれば、私はおそらくファンを打つでしょう。:-D
Dyin

@jnrbsn彼が言ったことについてアダムに同意しますか?
Basit

5

個人的にはPDOを使っていますが、それは主に好みの問題だと思います。

PDOには、SQLインジェクション(プリペアドステートメント)を再実行するのに役立ついくつかの機能がありますが、SQLに注意を払えば、mysqliでもそれを実現できます。

別のデータベースに移動することは、PDOを使用する理由ではありません。「特別なSQL機能」を使用しない限り、あるDBから別のDBに切り替えることができます。ただし、たとえば「SELECT ... LIMIT 1」を使用するとすぐに、「SELECT TOP 1 ...」であるMS-SQLにアクセスできなくなります。これはとにかく問題があります。


22
MySQLiはステートメントを準備しました。
タワー

5

回答を編集しました。

これらのAPIの両方である程度の経験をした後、mysqliをネイティブの準備されたステートメントで使用できなくする2つのブロッキングレベル機能があると思います。
彼らはすでに2つの優れた(まだ過小評価されている)回答で言及されていました:

  1. 任意の数のプレースホルダーへの値のバインド
  2. 単なる配列としてデータを返す

(両方ともこの回答で言及されています

何らかの理由でmysqliが両方で失敗しました。
最近では、2番目のバージョンget_result関数)ますが、mysqlndインストールでのみ機能するため、スクリプトでこの関数に依存することはできません。

それでも、今日まで値によるバインドはありません。

したがって、選択肢は1つだけです。 。PDO

以下のような他のすべての理由

  • 名前付きプレースホルダー(この構文シュガーはかなり過大評価されています)
  • さまざまなデータベースのサポート(実際には誰も使用していません)
  • オブジェクトへのフェッチ(役に立たない構文の砂糖)
  • 速度差(なし)

それほど重要ではありません。

同時に、これらの両方のAPIには、以下のような実際に重要な機能がいくつかありません

  • 識別子プレースホルダー
  • 動的なバインディングを煩わしさからなくすための複雑なデータ型のプレースホルダー
  • より短いアプリケーションコード。

したがって、実際のニーズをカバーするには、これらのAPIの1つに基づいて、手動で解析されたプレースホルダーを実装する独自の抽象化ライブラリを作成する必要があります。この場合、抽象化のレベルが低いmysqliを使用します。


最後に、人生の事実を知っていて否定しない誰か...
Ihsan

4

私のベンチマークスクリプトでは、各メソッドが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よりも少し低速ですが、それでも高速です(SELECT NULLを除く)。


17
PGOとは そして33秒速くなりますか?私はそれを信じることは非常に難しいと思います...
Alix Axel

3

MySQLiが私が本当に好きではないことをPDOが持っていることの1つは、PDOが指定されたクラス型(例:)のオブジェクトとして結果を返す能力$pdo->fetchObject('MyClass')です。MySQLi fetch_object()stdClassオブジェクトのみを返します。


19
実際には、クラスを手動で指定できます: "object mysqli_result :: fetch_object([string $ class_name [、array $ params]])"。stdClassは、何も指定しない場合にのみ使用されます。
Andrioid

-4

心に留めておくべきことが1つあります。

Mysqliは、列名を表すキーを持つ列を返すfetch_assoc()関数をサポートしていません。もちろん、それを行うために独自の関数を作成することは可能ですが、それほど長くはありませんが、私はそれを書くのに本当に苦労しました(非信者の場合:簡単に思われる場合は、しばらくして自分で試してみてください) t cheat :))


4
マニュアルを試しましたか?php.net/manual/en/mysqli-result.fetch-assoc.php
ティル

2
以前に実装していたのですが、はい、マニュアルを確認しました。準備されたステートメントで動作しますか?疑わしい...
マイク

2
実際、奇妙なことに部分的にサポートされています。通常のクエリでは配列をフェッチできますが、パラメータ化されたクエリではフェッチできません:-!
アルバロ・ゴンサレス

1
明らかに間違っている答えを削除してみませんか?
Majid Fouladpour 2012

2
@MajidFouladpour-答えは明らかに間違っていませ。一部のコンテキストが欠けています。Mysqliは連想配列の取得を完全にはサポートしていませ
アルバロ・ゴンサレス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.