データベース抽象化-複数の構文をサポート
-
03-07-2019 - |
質問
私が取り組んでいるPHPプロジェクトでは、複数のデータベースプラットフォームをサポートするためにいくつかのDAL拡張機能を作成する必要があります。これに関する主な落とし穴は、プラットフォームごとに構文が異なることです。注目すべきMySQLとMSSQLはまったく異なります。
これに対する最善の解決策は何ですか?
これまでに説明したカップルがあります:
クラスベースのSQL構築
これには、SQLクエリをビット単位で作成できるクラスを作成する必要があります。例:
$stmt = new SQL_Stmt('mysql');
$stmt->set_type('select');
$stmt->set_columns('*');
$stmt->set_where(array('id' => 4));
$stmt->set_order('id', 'desc');
$stmt->set_limit(0, 30);
$stmt->exec();
ただし、1つのクエリに対して非常に多くの行が含まれます。
SQL構文の再フォーマット
このオプションははるかにクリーンです-SQLコードを読み取り、入力および出力言語に基づいて再フォーマットします。ただし、解析が行われる限り、これははるかに遅いソリューションであることがわかります。
解決
クラスベースのSQL構築を推奨し、 Doctrine 、 Zend_Db または MDB2 。ええ、単純な選択を記述するためにより多くの行が必要ですが、少なくともパーサーに依存するようになり、ホイールを再発明する必要がなければなります。
DBALを使用することは速度のトレードオフであり、データベースの実行だけでなく、どちらかを初めて使用するときは、実際に慣れているときよりも苦痛になります。また、生成されたコードが最速のSQLクエリではないことはほぼ100%確信していますが、それは以前に意図したトレードオフです。
最終的にはあなた次第ですので、私はそれをやらないし、不可能ではないことは確かですが、独自のDBALを実装することで(長期的に)時間とリソースを実際に節約できるかどうかは疑問です。
他のヒント
解決策は、IDのような異なるプラットフォームに対して異なるクエリセットを持つことです
MySql:GET_USERS =" SELECT * FROM users"
MsSql:GET_USERS = ...
PgSql:GET_USERS = ...
その後、起動時に必要なクエリのセットを読み込み、参照します
Db :: loadQueries(platform):
$ users = $ db-> query(GET_USERS)
このようなスキームでは、SQLが提供するすべての機能が考慮されないため、各DBのすべてのテーブルに対してコード生成のストアドプロシージャを使用する方がよいでしょう。
データベースモデルをより多く認識している(つまり、結合を行っているか、ユーザーを認識しているため、各ベンダーに最適化されている)パラメーター化されたストアドプロシージャを使用する場合でも、それは優れたアプローチです。データベースインターフェースレイヤーは、アプリケーションに単なるテーブル以上のものを提供するものだと常に考えています。そのアプローチは、帯域幅を消費し、往復の無駄が多いためです。
それをサポートするバックエンドのセットがある場合、ストアドプロシージャを生成して契約を形成することが最善のアプローチであることに同意します。ただし、ストアドプロシージャに関して機能が制限されているバックエンドがある場合、このアプローチは機能しません。この場合、abstactionレイヤーを構築してSQLを実装するか、抽象/制限付きsql構文に基づいてターゲット固有のsqlを生成します。