web-dev-qa-db-ja.com

ORMまたはプレーンSQLを使用していますか?

私が開発したいくつかのアプリ(その後、忘れてしまった)については、主にMySQL用のプレーンなSQLを書いてきました。 SQLAlchemy のようにpythonでORMを使用しましたが、長い間それらに固執しませんでした。通常、それはドキュメンテーションまたは複雑さ(私の観点から)でした。

移植性のためにORMを使用します。1種類のデータベースを使用する場合はプレーンSQLを使用します。データベースのサポートが必要なアプリを開発するときに、ORMまたはSQLをいつ使用するかについてのアドバイスを本当に探しています。

それについて考えると、軽量のラッパーを使用してデータベースの不整合を処理する方が、ORMを使用するよりもはるかに良いでしょう。

233
hydrapheetz

ORMにはいくつかの素晴らしい機能があります。データベース列をオブジェクトフィールドにコピーするというわずらわしい作業の多くを処理できます。通常は、言語の日付と時刻のタイプを適切なデータベースタイプに変換します。通常、ネストされたオブジェクトをインスタンス化することにより、1対多の関係も非常にエレガントに処理されます。 ORMの長所と短所を念頭に置いてデータベースを設計すれば、データベースにデータを出し入れする手間が大幅に節約されます。 (それらをマッピングする必要がある場合、多態性と多対多の関係をどのように処理するかを知りたいでしょう。ORMを「コンピューターサイエンスのベトナム」と呼ぶ「インピーダンスミスマッチ」のほとんどを提供するのはこれら2つのドメインです。 )

トランザクション型のアプリケーションの場合、つまり、リクエストを行い、オブジェクトを取得し、それらをトラバースしてデータを取得し、Webページにレンダリングします。パフォーマンスへの負担は小さく、多くの場合、ORMはオブジェクトをキャッシュするため高速になります前に見たように、そうでなければ、データベースに複数回クエリを実行することになります。

レポートが多いアプリケーション、またはリクエストごとに多数のデータベース行を処理するアプリケーションの場合、ORMの税ははるかに重く、アプリケーションのキャッシュは大きな無駄なメモリ占有の負担になります。その場合、単純なSQLマッピング(LinQまたはiBatis)またはシンDALでの手作業でコーディングされたSQLクエリが最適です。

大規模なアプリケーションについては、両方のアプローチを使用していることに気付きます。 (簡単なCRUDの場合はORM、レポートの場合はSQL/thin DAL)。

163
Cameron Pope

Hibernate、EclipseLink、Toplink、OpenJPAなどを含むJPA(Java Persistence API、基本的にはJava/J2EE/EJB用の標準ORM API)でかなりの時間を費やした人として、私は私の一部を共有します観察。

  1. ORMは高速ではありません。それらは適切である可能性があり、ほとんどの場合は適切であるが、大容量で低遅延の環境では無意味です。
  2. JavaやC#などの汎用プログラミング言語では、それらを機能させるために非常に多くの魔法が必要です(たとえば、Javaでのロード時の織り方、計測など)。
  3. ORMを使用する場合、SQL(これは意図と思われる)からさらに進むのではなく、XMLおよび/またはアノテーション/属性を微調整してORMがパフォーマンスの高いSQLを生成するのにどれだけの時間を費やすかに驚くでしょう。
  4. 複雑なクエリの場合、実際には代替手段はありません。 JPAのように、生のSQLにある単純に不可能なクエリがいくつかあり、JPAで生のSQLを使用する必要がある場合、それはきれいではありません(C#/。Netには少なくとも動的な型があります--var-- Object配列よりも優れています);
  5. ORMを使用する場合、非常に多くの「落とし穴」があります。これには、意図しないまたは予期しない動作、データベースに対するSQL更新を実行する機能を組み込む必要があるという事実が含まれます(JPAでrefresh()を使用するか、JPAはデフォルトですべてをキャッシュするため、直接データベースをキャッチしないため)更新-直接的なSQL更新の実行は、一般的な運用サポートアクティビティです);
  6. オブジェクトとリレーショナルの不一致は常に問題を引き起こします。このような問題では、抽象化の複雑さと完全性の間でトレードオフがあります。時には、JPAが行き過ぎて、複雑なヒットが抽象化によって正当化されなかった場合に、収益を減少させる実際の法則にぶつかったと感じました。

もう少し説明が必要な別の問題があります。

Webアプリケーションの従来のモデルでは、永続化レイヤーとプレゼンテーションレイヤーを使用します(サービスまたは他のレイヤーが間にある場合がありますが、これらはこの説明の重要な2つです)。 ORMは、永続層からプレゼンテーション層(つまりエンティティ)までの固定ビューを強制します。

生のSQLメソッドの批判の1つは、単に1つのクエリで使用されるこれらすべてのVO(値オブジェクト)またはDTO(データ転送オブジェクト)になることです。これはORMの利点として宣伝されています。

つまり、これらの問題はORMで解消されるのではなく、単にプレゼンテーション層に移動するだけです。クエリ用のVO/DTOを作成する代わりに、通常はすべてのビューに1つずつ、カスタムプレゼンテーションオブジェクトを作成します。これはどうですか?私見ではありません。

これについて ORMまたはSQL:まだありますか? で書きました。

私が選択した永続化テクノロジー(Javaの場合)は最近、ibatisです。 JPAができることの90%以上を実行するSQLの非常に薄いラッパーです(十分に文書化されていませんが、関係の遅延ロードも実行できます)が、オーバーヘッドは(複雑さと実際のコードに関して)はるかに少ないです。

これは、昨年私が書いていたGWTアプリケーションで出てきました。 EclipseLinkからサービス実装のプレゼンテーションオブジェクトへの多くの翻訳。 ibatisを使用していた場合は、ibatisを使用して適切なオブジェクトを作成し、それらをスタックの上下に渡す方がはるかに簡単でした。一部の純粋主義者は、これがBad™であると主張するかもしれません。そうかもしれませんが(理論的には)、私はあなたに次のことを伝えます。それにより、コードが単純になり、スタックが単純になり、生産性が向上します。

243
cletus

ReadsのプレーンSQL、CUDのORMと言います。

パフォーマンスは、特にWebアプリケーションで常に懸念されるものですが、コードの保守性と可読性も重要です。これらの問題に対処するために、 SqlBuilder と書きました。

41
Max Toro

ORMは単なる移植性ではありません(ORMを使用しても実現するのは難しいです)。基本的に、永続的なストアを抽象化する層です。ORMツールを使用すると、定型的なSQLクエリ(PKまたは述語、挿入、更新、削除による選択)を記述せずに、問題の領域に集中できます。

14
Anton Gogolev

インピーダンスの不整合を処理するためだけに、立派な設計ではデータベースを抽象化する必要があります。しかし、最も単純な最初のステップ(およびほとんどの場合に適切)は、ヘビーウェイトORMではなくDALになると予想しています。あなたの唯一のオプションは、スペクトルの終わりにあるものではありません。


DALとORMを区別する方法を説明するように要求するコメントに応じて編集します。

DALは、テーブルをカプセル化し、フィールドをプロパティにマップするクラスから始めて、自分で作成したものです。 ORMは、DBMSスキーマの他のプロパティ(主にPKおよびFK)から推測された、ユーザーが記述しないコードまたは抽象化メカニズムです。 (これは、自動抽象化が漏れ始めるかどうかを調べる場所です。意図的にそれらを通知することを好みますが、それは私の個人的な好みかもしれません)。

11
dkretz

すべてのツールには目的とビジョンがあります。私は http://www.jooq.org/ を作成しましたが、iBatisはおそらくあなたにとっても良いソリューションではありますが、まさにあなたのニーズに合っています。

jOOQには基本的なORM機能がありますが、主に、ニーズに最適なORMを見つけようとするとき、ほとんどの開発者が最も必要とするものに焦点を当てています。

  • コード生成
  • 変数バインディング(JDBCの苦痛)
  • SQL構文の抽象化(構文エラーを防ぐため)

しかし、多くの場合、それらは行き過ぎて非常に多くの抽象化を提供するため、RDBMSに対して実行されているとは思わないでしょう。一方、RDBMSを選択した理由はまさに

  • 堅牢なデータソースです
  • SQLは、多くの優れたパフォーマンスを実現できます(ネストされた選択、結合、複雑な結合など)。多くの場合、ORMはこれらのことを実行できません。
  • トランザクションとセッションを自分で処理できます
  • uDTとストアドプロシージャがある

jOOQはこれらのポイントに正確に対応します。 JDBCと同様に機能しますが、痛みはありません。

7
Lukas Eder

私のORMを本当に活用させた鍵は、コード生成でした。コードパフォーマンスの観点から、ORMルートは最速ではないことに同意します。しかし、中規模から大規模のチームがある場合、特にCIを使用している場合、ビルドプロセスの一部としてDBからクラスとマッピングを再生成する機能がDBによって急速に変化しているのは注目に値します。あなたのコードは最速ではないかもしれませんが、あなたのコーディングはそうなります-私はほとんどのプロジェクトでどちらを採用するか知っています。

私の推奨事項は、スキーマがまだ流動的である間にORMを使用して開発し、プロファイリングを使用してボトルネックを検出し、生のSQLを使用してそれを必要とする領域を調整することです。

別の考えとして、Hibernateに組み込まれたキャッシングは、適切な方法で使用すると、多くの場合、パフォーマンスが大幅に向上する可能性があります。参照データを読み取るためにDBに戻る必要はもうありません。

6
MrTelly

フレームワークを使用するかどうかのジレンマは、現代のソフトウェア開発シナリオでは非常に一般的です。

理解することが重要なのは、すべてのフレームワークまたはアプローチに長所と短所があることです-たとえば、経験上、ORMはトランザクション、つまり挿入/更新/削除操作を処理するときに便利ですが、複雑なデータをフェッチする場合はその結果、ORMツールのパフォーマンスと有効性を評価することが重要になります。

また、フレームワークまたはアプローチを選択し、その中のすべてを実装することは必須ではないことを理解することが重要です。つまり、ORMとネイティブクエリ言語を混在させることができます。多くのORMフレームワークは、ネイティブSQLのプラグインに拡張ポイントを提供します。フレームワークやアプローチを使いすぎないようにする必要があります。特定のフレームワークまたはアプローチを組み合わせて、適切なソリューションを提供できます。

ORMは、挿入、更新、削除、高レベルの同時実行によるバージョン管理に関して使用できます。また、レポート生成と長いリストにネイティブSQLを使用できます。

5

「1つのツールですべてに対応する」ソリューションはありません。これは、「or/mを使用するかどうか」という質問にも当てはまります。 '。

私は言うだろう:あなたが非常に他のロジックなしで非常に「データ」に焦点を合わせたアプリケーション/ツールを書く必要がある場合、SQLはこの種のアプリケーションのドメイン固有言語であるため、プレーンSQLを使用します。

一方、多くの「ドメイン」ロジックを含むビジネス/エンタープライズアプリケーションを作成する場合、このドメインをコードで表現できる豊富なクラスモデルを作成します。そのような場合、OR/Mマッパーは、多くの配管コードを手から取り出すので、そうするのに非常に役立ちます。

4

私はこの質問が非常に古いことを知っていますが、私のように誰かが出くわした場合に備えて答えを投稿すると思いました。 ORMは長い道のりを歩んできました。実際には、開発の生産性の向上とパフォーマンスの維持という両方の長所を備えています。

SQLデータをご覧ください( http://sqldata.codeplex.com )。すべてのベースをカバーするc#用の非常に軽量なORMです。

参考までに、私はSQL Dataの著者です。

2
tjscience

機能するlikeSQLを使用しますが、コンパイル時のチェックと型の安全性を提供するORMを使用します。私のお気に入りのように: データ知識オブジェクト (開示:私はそれを書きました)

例えば:

for (Bug bug : Bug.ALL.limit(100)) {
  int id = bug.getId();
  String title = bug.getTitle();
  System.out.println(id +" "+ title);
}

完全にストリーミング。セットアップが簡単です(定義するマッピングはありません-既存のスキーマを読み取ります)。結合、トランザクション、内部クエリ、集計などをサポートします。SQLでできることはほとんど何でも。そして、巨大なデータセット(金融時系列)から些細な(Android)までずっと証明されています。

1
keredson

私が開発したアプリの1つは、Pythonで作成されたIRCボットでした。使用するモジュールは個別のスレッドで実行されますが、sqliteを使用するときにスレッドを処理する方法がわかりません。ただし、別の質問の方が良いかもしれません。

タイトルand実際の質問の両方を書き直すべきでした。どの言語でも、以前にDALを実際に使用したことはありません。

1
hydrapheetz

「妥協点があります!」という返信のコーラスに私の声を加えたいと思います。

アプリケーションプログラマーにとって、SQLは、制御したいことと、制御に煩わされたくないことをほぼ確実に混在させたものです。

私が常に望んでいたのは、完全に予測可能な決定を担当するレイヤー(DAL、ORM、またはマイクロORMと呼びますが、どちらでもかまいません)(SQLキーワードの綴り方、括弧の位置、タイミング列エイリアス、2つのfloatとintを保持するクラス用に作成する列を作成するために...)、SQLの高レベルの側面、つまりJOINの配置方法、サーバー側の計算、 DISTINCT、GROUP BY、スカラーサブクエリなど。

だから私はこれを行う何かを書いた: http://quince-lib.com/

C++用です。それがあなたが使用している言語であるかどうかはわかりませんが、「中間」がどのように見えるかについてこれが見られるのはおもしろいかもしれません。

1
slyqualin