ORMまたはプレーンSQLを使用していますか?[閉まっている]


245

私が開発した一部のアプリ(その後、忘れがちになりました)については、主にMySQL用のプレーンSQLを作成しています。SQLAlchemyのようなPythonでORMを使用してきましたが、長い間それらにこだわりませんでした。通常、それはドキュメントか、または(私の観点から)複雑さのどちらかが私を妨げていました。

私はそれを次のように見ています。移植性のためにORMを使用します。1つのタイプのデータベースを使用するだけの場合は、プレーンSQLを使用します。データベースのサポートを必要とするアプリを開発するときに、ORMまたはSQLをいつ使用するかについてのアドバイスを本当に探しています。

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


標準化、セキュリティ、保守性、言語の抽象化、DRYなど
ベン

ORMを使用したパフォーマンスは、SQLの近くにすることができ、あなたはそれを正しく使用している場合に依存し、正しい設定で...速くEF6.x 5倍を作ることがHOを参照してください:linkedin.com/pulse/...
baHI

:ORMのアーキテクチャでは、どのよう-に(何を避けるために)、ここに私の別のリンクですlinkedin.com/pulse/...
baHI

オブジェクトリレーショナルマッピング(ORM)は、多くのプログラミング言語ですでに非常に人気があり、SQLの最良の代替手段の1つです。私は、TRIADBプロジェクト用のCQLを作成するためのメソッドチェーンスタイルからインスピレーションを受けました。healis.eu/triadb/#latest-release
Athanassios

2
この質問が閉じられたのはばかげています。
ミッチウィート

回答:


169

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

トランザクション型のアプリケーション、つまり要求を出し、いくつかのオブジェクトを取得し、それらをトラバースしていくつかのデータを取得し、それをWebページにレンダリングする場合、パフォーマンス税は小さく、多くの場合、ORMはオブジェクトをキャッシュするので高速にできます前に見たように、それ以外の場合はデータベースを複数回照会することになります。

レポートが多いアプリケーション、または要求ごとに多数のデータベース行を処理するアプリケーションの場合、ORM税ははるかに重く、それらが行うキャッシュは、大きくて無駄なメモリを大量に消費します。その場合、シンDALでの単純なSQLマッピング(LinQまたはiBatis)または手動でコーディングしたSQLクエリが適しています。

私は、両方のアプローチを使用している大規模なアプリケーションを見つけました。(簡単なCRUDのORMおよびレポート用のSQL /シンDAL)。


「リクエストごとに多数のデータベース行」を定義できますか?:)
Mosselman

たとえば、JPAをIBatisと統合できますか?ANを同じトランザクションで機能させますか?
Jaime Hablutzel、2011年

2
誰も議論していないように見えるもう1つの考慮事項は、基本的な状態管理です。フレームワークのこのスタック全体(JSF、JPAなど)は、Java Beanのget / setメソッドに基づいています。これは、すべてのテーブル、すべての列、すべてのボイラープレートのTONです...これが本当のアンチパターンです:すべてのフィールドを公開されているかのように公開するだけです。実際には、オブジェクト/テーブル/行のフィールドにget / setメソッドを持つことは、情報の非表示とカプセル化のすべてのテナントに違反することに非常に近くなります。最後に、状態管理に戻ります...不変性オプションはどこにありますか?ハーフセットオブジェクトは許可されますか、それとも許可されますか?ほとんどのオプションはありません。
ダレルティーグ

2
この回答の重要な声明に特に注目し、同意します。「リクエストごとに多数のデータベース行を処理するアプリケーションの場合、ORM税ははるかに重い」ほとんどの開発者はSQLがあまり得意ではないため、ORMは開発者とメンテナンスにのみ適していますが、実際にパフォーマンスについて語っている場合、SQLは完全にそれよりも優れています。
Manachi

「ほとんどの開発者はSQLがあまり得意ではありません」??? ほとんどの開発者は、LINQ、式ツリーの能力、および一般的なORM、コード生成、その他の多くを適切に使用する方法を知らないと思います。しかし、いいえ、私はそのような強力な発言をする根拠はありません。
AdanayMartín2017

253

HPA、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-が多くあります)オブジェクト配列よりも良い);
  5. ORMを使用する場合、非常に多くの「落とし穴」があります。これには、意図しない動作や予期しない動作、データベースへのSQL更新を実行する機能を組み込む必要があるという事実が含まれます(JPAはデフォルトですべてをキャッシュするため、JPAまたは類似のメソッドでrefresh()を使用して、直接データベースをキャッチしないためです。更新-直接SQL更新の実行は、一般的な実稼働サポートアクティビティです。
  6. オブジェクトとリレーショナルの不一致は常に問題を引き起こします。このような問題があると、抽象化の複雑さと完全性の間にトレードオフがあります。時々、JPAが行きすぎて、複雑さのヒットが抽象化によって正当化されないリターンを減少させる本当の法則にぶつかると感じました。

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

Webアプリケーションの従来のモデルは、永続化レイヤーとプレゼンテーションレイヤーを使用することです(おそらくサービスと他のレイヤーが間にありますが、これらはこの議論にとって重要な2つです)。ORMは、永続化レイヤーからプレゼンテーションレイヤー(つまりエンティティ)まで厳密なビューを強制します。

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

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

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

最近、Javaで選択した永続化テクノロジはibatisです。これは、JPAが実行できる機能の90%以上を実行するSQLのかなり薄いラッパーです(十分に文書化されていませんが、関係のレイジーロードを実行できます)が、オーバーヘッドははるかに少なくなっています(複雑さと実際のコードの観点から)。

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


2
私は、このようなことに関するリソースを収集するためだけに、別の(コミュニティーではwikiを使用していますが)質問を投稿するように促されました。最後の段落について:私は単純さが好きです。おそらく多すぎる。
hydrapheetz 2009年

3
iBATISは素晴らしいですが、jOOQ:jooq.sourceforge.netを試してみてください。その主な焦点は、あなたが言及した6つの理由により、SQLに近づくことです。
Lukas Eder

5
ポイント3の+1。ORMを使用すると、SQLを完全に理解する必要がなくなると多くの人が感じています。ことは、SQLを使って体操をすることができる/習得すると、おそらくORMからすぐに離れてしまうことに気付くでしょう...
ライアンフェルナンデス

4
つまり、2013年の終わりであり、ご存じのように、「古い事実」ほど誤解を招くものはないでしょう。それでも、あなたの主張が変わらないかどうかお伺いしてもよろしいでしょうか。そうでない場合は、ブログ投稿を書いたり、それに応じて回答を更新したりできると便利です。
ドミニク

3
varは.NETで動的な型を生成しません。dynamicキーワードを持つ変数は、.NETで動的な型です。varはまだ静的型付けです。stackoverflow.com/questions/961581/…を
Fazi

45

R eads にはプレーンSQL 、CUDにはORM と言います。

パフォーマンスは、特にWebアプリケーションだけでなく、コードの保守性と可読性にも常に関心があります。これらの問題に対処するために、SqlBuilderを作成しました


1
CUDとは?定義が見つかりません。
キムチマン

27
@KimchiMan CRUD、Rなし
Max Toro

3
CUD-作成、更新、削除。
2017年

14

ORMは単なる移植性ではありません(これは、ORMを使用しても実現するのが難しい)。ORMツールがボイラープレートSQLクエリ(PKによって、または述語、挿入、更新、削除によって選択)を書くことから解放され、問題のあるドメインに集中できるようになる場合、基本的には永続ストアに対する抽象化レイヤーです。


3
データベースのフレーバー間の移植性に近いものを考えていました。質問を深夜に投稿するべきではありません。
hydrapheetz 2009年

1
それがまさに私が言っていたことです。最も基本的なシナリオでさえ、異なるNULLの処理など、異なるDBMSでエラーが発生する可能性があります。
アントンゴゴレフ2009年

ORMはオブジェクト間の関係を抽象化するレイヤーを提供しますが、あなたが言及するボイラープレートクエリに関しては大きな利点はありません。JDBCアプリでは、抽象スーパークラスまたはユーティリティクラスに少量のコードでこれらのタイプのクエリを記述できます。新しいテーブルごとにボイラープレートを繰り返す必要はありません。
Kevin Stembridge、2011年

11

立派な設計では、インピーダンスの不一致を処理するためだけに、データベースの抽象化が必要になります。しかし、最も単純な最初のステップ(およびほとんどの場合に適切)は、ヘビー級のORMではなく、DALであると期待します。あなたの唯一の選択肢は、スペクトルの端にあるものではありません。


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

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


2
DALとORMの間にどこで線を引きますか?
混沌

4
それで、あなたがORMの作者なら、あなたのORMは自動的にDALに戻りますか?:)
Bombe

DAL = Persistence LayerとORMは、DAL内でデータストアへのCRUD操作を実行するために使用するツールです。
Vahid Ghadiri

7

どのツールにも目的とビジョンがあります。私はあなたのニーズにぴったり合うようにhttp://www.jooq.org/を作成しましたが、iBatisはおそらくあなたにとっても良い解決策ですが。

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

  • コード生成
  • 変数バインディング(これはJDBCの問題です)
  • SQL構文の抽象化(構文エラーを防ぐため)

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

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

jOOQはこれらの点に正確に対応しています。JDBCと同じように機能しますが、痛みはありません。


6

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

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

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

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


3
ORMが高い同時実行性に優れているのはなぜですか?
user359996 2011年

6

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

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

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


2
絶対に個人的な好みの問題。私にとって、コード生成は欠陥です。
dkretz 2009年

5
2番目の段落を読んでください....完全性も役に立つでしょう
MrTelly

コード生成は、特定のタスクをより速く実行するための唯一の方法です。他のすべてのツールと同様に、強力で災害につながる可能性があります。技術的には、すべての言語が他のタイプのコードを生成しています。
Banjocat、2015年

4

「one-tool-fits-all」ソリューションはありません。これは、「or / mを使用する必要があるかどうか」という質問にも当てはまります。'。

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

一方、多くの「ドメイン」ロジックを含むビジネス/エンタープライズアプリケーションを作成する場合は、このドメインをコードで表現できるリッチクラスモデルを作成します。このような場合、OR / Mマッパーを使用すると、多くの配管コードを手に入れることができるため、正常に実行するのに非常に役立ちます。


「「1つのツールですべてに対応できる」ソリューションはありません。
ルシノ、2011年

1

私が開発したアプリの1つは、Pythonで書かれたIRCボットでした。それが使用するモジュールは別々のスレッドで実行されますが、sqliteを使用しているときにスレッドを処理する方法を理解していません。ただし、別の質問の方がよい場合があります。

タイトル実際の質問の両方を言い換えればいいだけです。これまで、どの言語でもDALを使用したことがありません。


4
まあ、私はあなたがすべきだという意見です。あちこちで生のSQLを使用するのはかなり大変です。
混沌

まあ、そうだろう。私が時々ハックするフォーラムソフトウェアがあり、そこにはたくさんのmysql_query()とmysql_result()があります。それはナッツです。
hydrapheetz 2009年

この「アプリ」のことは何ですか?
Zoran Pavlovic

この質問がircボットアプリで質問され、それが何であるか(非常に役立つガイド)になったのはおかしいです!ircボットアプリはスケールの一方の端にあり、20を超える開発者がそれに取り組んでいる複雑な結合と数百万のデータ行を持つ50-100以上のテーブルを備えたアプリケーションは、スケールのもう一方の端にあります。スケールの「ircボットアプリ」の終わりになると、それはほとんど問題になりません。
Manachi

1

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

例えば:

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

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


IDEは、このような静的チェックを直接提供することもできます(IDEAはDB構造を知っているので、DBの場所/ DDLファイルがどこにあるかを伝えることができるため、SQLクエリ/手順/その他で型チェック/関係チェックなどを行うことができます)
Xenos、

それは便利です。ビルド/ CIステップの一部としてそれを行うことができますか?SQLと他の文字列をどのように分類しますか?文字列操作、または文字列定数のみを処理できますか?
keredson、

私はabBlockによってブロックされますが、IntelliJは他の言語のjetbrains.com/datagrip/featuresと同様にSQLを解析するため、CI / CD / buildに統合できます(SQL解析コードを分離するようにIJチームに依頼するか、おそらくSonarはすでにそうです)そのようなパーサーを持っています)。解析によりデータ型がもたらされるので、それらにチェックを追加できます(私はカスタムプラグインでこれを行いました)、または「JOIN列にFKインデックスがあるか?などが挙げられる。これらは、ネイティブIJのSQL検査にきちんとも改善だろう
Xenosの

1

私はこの質問が非常に古いことを知っていますが、誰かが私のように出くわした場合に備えて、回答を投稿すると思いました。ORMは長い道のりを歩んできました。それらのいくつかは、実際に両方の世界の最高のものを提供します:開発の生産性を高め、パフォーマンスを維持します。

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

ちなみに、私はSQLデータの作者です。


1

「中途半端だ!」という合唱に声を入れたい。

アプリケーションプログラマにとって、SQLは、制御したいことと、ほぼ間違いなく制御したくないことの混合です。

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

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

それはC ++用です。それがあなたが使用している言語かどうかはわかりませんが、これと同じように、「中間層」がどのように見えるかについてこの見解を見るのは興味深いかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.