一括操作を実装する必要がある場合、ORMフレームワークを放棄する必要がありますか?


15

一般的な状況は次のとおりです。

  • ORMフレームワークを使用するアプリケーションに一括操作を実装する必要があります。
  • 最初のパスの後、重大なパフォーマンスの問題に気づきました。

ここに私の質問があります:

  • この状況では、生のSQLを含むソリューションを好むべきでしょうか?
  • または、ORMフレームワークを使用した一括操作に一般的に関連する問題を軽減するのに役立つ、よく知られた設計パターンはありますか?

編集:

  • アプリケーション全体からORMフレームワークを削除する必要があるかどうかは尋ねません。
  • 私は尋ねています:アプリケーションのこの小さなスライスのためにORMフレームワークを放棄する必要がありますか?

何をすべきかはわかりませんが、一括操作をバッチ処理しようとしましたか?
ChrisAnnODell

回答:


13

ORMは、データベースへのアクセスを完全に引き継ぐことを意図したものではありません。CRUDであるコードの80%にそれらを使用します。これは自分で書くには面倒すぎるものです。ストアドプロシージャ、動的SQL、または慎重に最適化する必要がある残りの20%に必要なものを使用します。


4
データベースの抽象化がORMの使用を決定した主な理由の1つではない場合、これは機能します。

@ Pierre303、あなたのコメントを理解するのに苦労しています。どういう意味ですか?
マーク・カンラス

@MarkCanlas:彼は「データベースを削除する」ことを意味すると思います。そうすれば、データベースを変更する(たとえば、SQL ServerからMySQLに変更する)ことができます。実際には、このユースケースはほとんど発生しません。
ロバートハーヴェイ

1
それでも抽象化を作成できます。複数のプロバイダー/方言を実際にサポートするほとんどのORMは、プロバイダー/方言固有のコードをサポートしています。特定のデータベースの一括挿入/配列バインディング/ TVP / whateverとして操作を実装し、SQLiteのようなサポートされていないプロバイダーの場合はスローバイスローにフォールバックできます。最悪の場合、ビルドまたは設定パラメータに基づいて、バルクになる可能性のある機能を別のインターフェイス/クラスとサブに分割して、異なる実装で実行できます。
アーロンノート

はい、特定の問題に対する特定のコードだけでなく、カスタム方言も役立ちます。ただし、これを財務的な観点で実行可能にするためには、これを厳密な最小値に制限する必要があります。私たちのカスタマイズトルートカスタム関数(方言)は、データアクセスコードベース全体の0.1%未満を表しています。それ以上であれば本当に心配です。

7

私は、高いパフォーマンスを必要とし、数十億のレコードを処理するアプリケーションでORM(nHibernate)を使用しています。時間の経過とともに、最も重大なパフォーマンスの問題は、ORMだけではなく、ORMの独自の使用方法に関連していることがわかりました。

ORMは、必須のデータベース知識を置き換えるものではありません。これは、コードの生産性と柔軟性を高めるために使用するツールですが、パフォーマンスを最適化するには、基礎となるプロセスを知る必要があります。

特定のORMを指定しなかったため、パフォーマンスを改善するために行った操作は次のとおりです。

  • ORMプロファイラーを使用しました。(nhprofを使用しました)
  • データベースプロファイラーを使用しました。(SQL Server Profilerを使用しました)
  • この件に関してできる限り多くの記事を読みます。(ドキュメントの主題に関する章全体に加えて、nHibernateの多くが利用可能でした)
  • パフォーマンスとスケーラビリティに関する特定の本を購入しました。
  • ベンチマークシステムを作成して、独自の最適化をテストしました。
  • さらに重要なことは、巨大なデータを使用して実際の顧客とコードをテストできたことです。最後のことだけでも、アプリケーションのほとんどの問題を見つけるのに役立ちました。

1

Entity Frameworkでなんとかできましたが、アプリケーションは多くのバッチスタイルの操作を行っていました(個々のテーブルに大量のレコードを書き込む)ので、ぴったりでした。アプリ内の特別な目的のコードの量を減らすために、可能であればORMフレームワークを保持できるかどうかは間違いなくわかります。書き込みをバッファリングしてから、それらをグループとして実行することは可能ですか?トランザクションのセマンティクスは失われますが、一括操作を行う場合は、すでにそれに対処していると思います。


1

ORMは魔法のようなことは何もしません。オブジェクトアクセスメソッドをSQLに変換します。それらが実行するSQLステートメントは、手動で作成するSQLよりも必ずしも低速ではありません。そうは言っても、つまずくかもしれない問題がいくつかあります。

  1. トランザクション:1つの大規模な一括操作は、一緒に同じことを達成する多くの小さなトランザクションよりもほとんど常に高速です。したがって、ORMメソッド呼び出しで詳細なトランザクションを使用する場合(たとえば、Spring Rooエンティティのアクティブなレコードスタイルのメソッドには、デフォルトで@Transactionalの注釈が付けられます)、一括操作は遅くなります。アプリケーションの場合は、トランザクションロジックを確認する必要があります。
  2. キャッシュ:Hibernateでは、1次キャッシュにより、エンティティマネージャーはデータベースへの不必要な往復を回避できます。一般的には良いことですが、不必要なキャッシュの詰まりを引き起こし、アプリケーションのパフォーマンスを低下させる一括挿入には適していません。それがあなたの問題であるなら、ChrisAnnODellによって上で提案されたバッチ処理パターンを見るべきです。インポーターで使用し、一括挿入を大幅に高速化します。

ネイティブSQLを使用してパフォーマンスを改善することは問題ありません。ただし、まず、何が遅くなっているのかを理解してください。


キャッシュを回避するには、StatelessSessionを使用します。また、IDの自動インクリメントを避けます。代わりに、HiLoまたはGuidを使用する必要があります。

1

ORMをバイパスします。それだけでなく、「通常の」SQLもバイパスします。データベースのバルクユーティリティを使用して、非常に大きなデータセットをステージングテーブルに挿入します。次に、sqlを使用してステージングアクティビティを実行します。

「ブログの味」ORMは、すべての状況で機能するとは限りません。


確かに、この種のバックエンドツールは習得するのに手間がかかりますが、約3〜4回すれば専門家になり、より速く、時には他の方法ではできないことができるようになります。それはシャベルとブルドーザーの違いのようなものです。テキスト入力ファイルを読み取り、低レベルの操作でデータを更新するために、さまざまなプラットフォーム用のスクリプト制御ツールを作成しました。そのようなツールを書くことは、あなたの人生を楽にすることもできます(または、少なくとももっと面白くなります)。このようなことを使用して、ソフトウェアの更新中にクライアントインストールのカスタマイズデータを調整できます。

0

そのような状況にあった。時々、あなたはしなければなりません。

一部のORMでは、開発者がオブジェクトモデルをスキップして、データベースレイヤーに直接進むことができます。

オブジェクト指向として、カプセル化された一括操作を使用するORMもあります。


0

umlcatで述べたように、バルク操作を使用できるORMがいくつかあります。

さらに良いことに、多くのORMは拡張可能であるため、まだサポートされていない場合は、バルク操作を実行する独自のメソッドを記述することができます。アプリケーションのバルク操作を除外できるものであれば、ORMのレイヤーとして追加します(そのためには、おそらく生のSQLを記述する必要があります)が、アプリケーションではORMを使用します実装したメソッド。

これにより、ユニットテストとデバッグも簡単になります。ORMメソッドのテストカバレッジが良好になったら、アプリで自由に使用できます。そうしないと、生のSQL(特にトランザクションと多くのJOINを含む大きなSQL)のデバッグが苦痛になります。

かつて、ほぼ100 LOCの生のSQL呼び出しでバグを見つけるのに1日近くかかりましたが、バグはたった1文字でした!それ以来、アプリに生のSQLが含まれないようにし、すべてのSQLプロシージャを個別に単体テストしました。


0

まあ、私が知っているデザインパターンはありません。私の推測では、あなたは何らかの理由でORMの決定を下したので、ORMを放棄することはおそらくあなたが望んでいることではないでしょう。ただし、これらの場合、両方のソリューションを混合する余地があると思います。あなたがソフトウェアでORMのデフォルトの使用から逸脱する理由を意識してそれを文書化する限り、それは間違っていません。その次に、いくつかのORMフレームワークには、一括操作を行うための機能があります。nHibernate(.NETフレームワークのORM)には、オーバーヘッドがはるかに少ないStatelessSessionsがありますが、それでも、探しているパフォーマンスの向上が得られない場合があります。その場合は、生のSQLを使用してください。

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