問題タブ [select-n-plus-1]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
sql - n+1 の問題を回避する最も高速な方法とその理由は?
レガシ アプリケーションで多くのn+1 の問題を回避するために、いくつかのユーティリティ メソッドを追加しようと考えています。
一般的なパターンは次のとおりです。
ClassA
レコード インスタンスのコレクションに取得されます
次に、サブインスタンスが遅延取得されます。
これにより、n+1 選択の問題が発生します。ほとんどの場合、ヒットする頻度の低いページで 2 つのインスタンスしか取得されないため、これは大きな問題ではありませClassA
んが、アプリケーションのスケーリングに伴い、この n+1 の問題によりページが遅くなりすぎる場所が増えています。
ClassA
インスタンスとClassB
インスタンスが一緒に取得されるように、このアプリケーションの既存のデータ アクセス コードの一部を置き換えようとしています。
これを行うには、次の 3 つの方法があると思います。
1)ClassA
今と同じようにインスタンスを取得してからClassB
、1 回の集約呼び出しでインスタンスを取得します。
これは 2 つの別個の DB 呼び出しであり、動的 SQL のクエリ プランはキャッシュできません (ID のリストのため)。
2) サブクエリでClassB
インスタンスを取得します。
これも 2 つの DB 呼び出しであり、クエリに対するクエリ[table-A]
は 2 回評価する必要があります。
3) すべてをまとめて、ClassA
インスタンスの重複を排除します。
これは 1 回の DB 呼び出しにすぎませんが、内容が[table-A]
繰り返されるようになりました。結果セットが大きくなり、DB からクライアントにデータを送信する時間が長くなります。
したがって、実際にはこれは 3 つの可能な妥協点です。
- 2 つの DB 呼び出し、クエリ キャッシュなし
- 2 つの DB 呼び出し、複雑なクエリが 2 回評価される
- 1 DB 呼び出し、非常に大きな結果セット
これらの 3 つのパターンは、任意の 1 つの親子ペアのテーブルに対してテストできますが、大量のテーブルがあります。私が知りたいのは、一貫してどのパターンが速いかということです。もっと重要なのはなぜですか?これらの妥協の 1 つは、明らかなパフォーマンスの低下要因ですか?
Linq、EF、NHibernate などの既存のメカニズムは何を使用していますか?
3つすべてよりも優れた4番目の方法はありますか?
nhibernate - 私はこの選択N+1を避けることはできません
私はこのマッピングを持っています(自動ページングコレクションのデモアプリで使用したので、adventureworksから取得しています)
および次の(限定された)クエリ:
従業員の連絡によって選択されたN+1を削除できません。どうすればよいですか?マッピングも変更できることを検討してください!
EDIT
:@cremorによって実用的なソリューションを追加します
これにより、問題が回避されます。
nhibernate - 複合キーでNHibernateN+1を回避するにはどうすればよいですか
編集私はこの1つの問題のためにプロジェクト全体を作り直しました。したがって、私は質問を作り直しました。
N+1とデカルト結合が4レベルの深さのエンティティと3番目のレベルの複合キーを結合することを効率的に回避できるようにしたいと思います。
これは、遅延ロードではなく、すべてのテーブルを結合するだけでなく、いくつかのクエリで実行されることを望んでいます。
A-(多)-> B-(多)-> C-(コンポジット、シングル)-> D
何かのようなもの:
使用したコードは次のとおりですこれは完全に機能するアプリです。NuGetを使用して、Sqlite x86、StructureMap、NHProf、FluentNHをインストールしました。
StructureMapServiceLocator:
AppRegistry
エンティティの一覧表示:
プログラム(コンソール):
c# - 同じ NHibernate クエリの実行が、MSTest 単体テストよりも WinForm プロジェクトで桁違いに遅いのはなぜですか?
本番環境でサービスとして実行されるアプリがありますが、単純な GUI を使用して手動でテストを行っています。実際には何も行われておらず、入力用のテキスト ボックスを備えた単なるラッパーです。
最近、データベース スキーマを変更し、マッピングを一致するように更新したところ、些細なケースで GUI の動作が突然非常に遅くなりました。ログを記録して何度も実行した後、新しいボトルネックは次のクエリであることが判明しました。
繰り返しますが、その 1 つのメソッドに 1:08 分かかりました (データベースには約 300 の FieldDefinitions しかありませんが)。この時点で、GUI を手動で再実行するのにうんざりしていたので、まったく同じケースを実行する単体テストを作成しましたが、スローダウンを再現できませんでした。
私のテストでは、GUI が同じ入力で行うのと同じトップレベル オブジェクトを呼び出しました。これはほぼ同じ時間で実行されると予想されます。しかし、MSTest を使用して Visual Studio で実行すると、同じクエリにかかる時間は 2 秒未満でした。30分の1の時間です。まったく同じ作業を行っていましたが、大幅に高速でした。
それらを同じように実行できるかどうかを確認するためにチェックしたこと:
- どちらの方法でも、同じ数の SQL ステートメントが生成されました。
- JITterが原因ではないようです(GUIを再起動せずに複数回実行すると、同じ時間が何度も発生します)
ISessionFactory
それぞれに新品を使用するように分離しRefresh
ても効果はありませんでした- ロギング (log4net) をオフにしても効果はありませんでした
子をeager-loadするようにクエリを変更するとうまくいきました...種類:修正を適用した後、WinFormsアプリは単体テストがすでに行われたのと同じくらい高速です。単体テストの速度は大幅に変わりませんでした (10 分の 1 秒)。
古いクエリがselect n+1
問題を引き起こしていましたが、この問題は Winform と MSTest の両方の実行に存在していました。そのため、WinForm アプリだけが大幅な速度低下を経験しました。
これをどのように説明できますか?Select N+1 クエリ中に WinForm アプリだけが大幅にスローダウンするのはなぜですか?
linq - 外部キーとLINQなしでN+1を選択するのはなぜですか?
残念ながら、実際の外部キーがないデータベースがあります(これは後で追加する予定ですが、移行を容易にするために今は追加しないことをお勧めします)。関係を設定するためにデータベースにマップするドメインオブジェクトを手動で作成しました(このチュートリアルhttp://www.codeproject.com/Articles/43025/A-LINQ-Tutorial-Mapping-Tables-to-Objectsに従って)。ついにコードが正しく実行されるようになりました。しかし、SELECT N+1の問題があることに気づきました。すべての製品を選択する代わりに、次のSQLで1つずつ選択されます。
コントローラ:
LINQ式が正しいかどうかわからなかったので、これを使用しようとしましたが、それでもN+1が得られました。
ドメインオブジェクト:
私は自分のビューからすべてをコメントアウトしようとしたので、これに影響を与えるものは何もないようです。ViewModelは見た目と同じくらい単純なので、そこに何も存在しないはずです。
これを読んだとき(http://www.hookedonlinq.com/LinqToSQL5MinuteOVerview.ashx)、データベースに実際の外部キーがなく、コードで手動結合を使用する必要があるのではないかと考え始めました。あれは正しいですか?どうすればいいですか?ドメインモデルからマッピングコードを削除する必要がありますか、それとも追加/変更する必要がありますか?
注:この質問をよりクリーンにするために、関連性がないと思われるコードの一部を削除しました。足りないものがあれば教えてください。
編集:Gert Arnoldは、1つずつ照会されることProducts
からすべての問題を解決しました。Category
ただしProducts
、ページに表示されているすべてのものが1つずつ照会されるという問題がまだ発生しています。
これは私のビューコードから起こります:
List.cshtml:
ProductSummary.cshtml:
もう一度.First()を使ったものですか?.Take(1)を試しましたが、とにかくIDを選択できませんでした...
編集:DataContextにアクセスするためのコードとDataLoadOptionsを作成するためのこのコードをリポジトリに追加しようとしました。ただし、ProductSubごとにクエリが生成されます。
ただし、生成されるSQLはわずかに異なり、クエリの順序も異なります。
ProductSubを選択するクエリの場合、DataLoadOptionsコードはという名前の変数を生成@x1
し、それらがない場合、変数はという名前になり@p0
ます。
私へのクエリの順序の違いは、DataLoadOptionsが実際に何かを実行していることを示していますが、私が期待していることではありません。私が期待するのは、次のようなものを生成することです。
java - JPA/Hibernateコンストラクタ式で「n+1選択」を防止しますか?
Item
とData
、および DTO クラス の2 つのエンティティがありItemData
ます。ItemData
で構成され、JPA マッピングはありませんItem
。Data
データが入力された ItemData のリストを取得するには、JPQL でコンストラクター式を使用します。
これが Hibernate が行っていることです: と の両方のデータを取得する代わりに、Item
最初Data
に ID を取得し、その後n 個の select ステートメントでデータを取得します。この動作を変更する方法はありますか?
ruby-on-rails - アクティブなレコードとのレール関係でN + 1?
私は4つのモデルを持っています
- グループ
- レポート
- コメント
- ユーザー
グループ => has_many => レポート
レポート => has_many => コメント
コメント => Belongs_to => ユーザー
グループを表示したいときは、次のようにします
この場合、N+1 クエリの問題を解決する最善の方法は何ですか??
nhibernate - NHibernate を使用してオプションの 1 対 1 を積極的にロードする
次の簡略化されたドメインを考えてみましょう。
MovieDetail
は なしでは存在できませんがMovie
、は なしで存在するMovie
可能性がありますMovieDetail
(つまり、詳細はわかりません)。
私たちのデータベースには、Movie
with columns用の別のテーブルと、 with columnsおよびId
用の別のテーブルがあります。からへの外部キーもあります。MovieDetail
Id
MovieId
MovieDetail.MovieId
Movie.Id
これはすべて NHibernate でマップされていますがMovie
、インスタンスのコレクションを取得するときは、 との左外部結合が必要MovieDetail
です。Movie
そうでない場合、インスタンスを反復処理するときに N+1 問題が発生する可能性があります。それが今のケースです。プロパティへの呼び出しごとに個別のクエリがありMovie.MovieDetail
ます。
マッピングを試みましone-to-one
たが、両方のインスタンスがある場合のようです。私たちの場合、常にMovieDetail
. また、それらは同じ主キーを共有しません。
数式を調査しましたが、それには自分のMovieDetail
implementを作成する必要がありIUserType
、基本的に NHibernate を自分のドメインに入れます。それは避けたいです。
hibernate - 注釈 @BatchSize が機能しない
オブジェクトを持つAccount
単一のJPAクラスを含む3つのJPAクラスがありますAddress
City
N+1 選択の問題を解決したかったので、クラスの上で @BatchSize を使用しようとしましたが、データベースへの N+1 呼び出しを停止しなかったため、自分で batchSize を設定する必要がありましたpersistence.xml
である1つのエンティティを除いて機能するAddress
ようになったので、都市とアカウントに対して1つのSQL選択を取得しますが、住所に対してはまだN SQL選択を取得します。唯一の違いは、アカウントとアドレスの関係が 1 対 1 であることです。
私の質問は次のとおりです。
- 1 対 1 の関係が、テーブル Address でまだ N を選択している理由でしょうか? なぜ?
- 注釈が機能しないのはなぜですか (なぜ に
persistence.xml
設定する必要があったのですか)、注釈を有効にするために行うべき設定はありますか?