2017-01-30 5 views
2

現在、アプリケーションを高速化する方法を調査しており、その大部分はエンティティのリスト(実際はテーブル)に関連しています。ソートされたデータのジョインによるHibernateページング

パラメータと要件

そのリストのパラメータと要件は(私はここでは関係のものを言及しようとするでしょう)次のとおりです。

  • 50万行がある場合もあります/リスト内のエンティティ
  • 一度に表示されるのは2つだけです。ここでページネーションを使用します。
  • ユーザーはリストに表示する列を選択できます(したがって、単一の「静的」なクエリを提供することはできません)。
  • これらのリスト列のほとんどは、ソート可能および/またはフィルタリング可能です。
  • エンティティには、リスト列のいくつかを提供する2対多関係があります。
  • これらのリスト列には、複数の値を含むことができます(これらは1つのセル内にリストとして表示されます)
  • 現在のユーザーの操作(編集、アップロードなど)に起因するデータの更新は、 (JPAのように)、以下の単純化されたエンティティを考えるモデルが少し明確にするために、できるだけ速くリスト(すなわち「immeditately」)

モデル:

class Car { 
    String manufacturer; 
    String model; 
    Date dateOfProduction; 
    List<TyreSize> allowedTyreSizes; 
    Set<Date> inspectionDates; 
} 

はしようとしないでください。それがjuだからあまりにも多くの意味をそのモデルに入れてstは問題を説明するためのものです(私たちのデータは、はるかに複雑ではありません)。ユーザーは、我々は、動的に必要なクエリを構築している、実行時に表示する列を選択することができますので

+==============+=======+=======+===============+=============+ 
| Manufacturer | Model | Prod. | Allowed Tyres | Inspections | 
+==============+=======+=======+===============+=============+ 
| BMW   | 320d |01/2016| - 225/40 R18 | - 01/07/16 | 
|    |  |  | - 225/45 R17 | - 13/12/16 | 
+--------------+-------+-------+---------------+-------------+ 
| Toyota  | Camry |09/2016| - 185/70 R13 | - 31/12/16 | 
+--------------+-------+-------+---------------+-------------+ 

:車の

「完全な」リストには、このようになります。それは今のところかなりうまくいっています。

基本的な問題

ソートやフィルタリング関与しているときに我々が抱えている問題はパフォーマンスです:我々の現在のアプローチは、ソートし、メモリにフィルタリングするために必要なすべてのデータをロードすることで、そこにソートやフィルタリングを行うと、並べ替えられたIDとそのページのリストを保持します。我々はこれがやや遅いことを認識していますが、これまでのところパフォーマンスは経営陣を満足させるほど十分でした。状況が変化しましたが、現在はより多くのデータを処理し、パフォーマンス要件が向上しています。

    :したがって

    我々は現在、私はまだこの(側)質問をするよデータベースでそれを行うためのアプローチを以下している間にすべてのデータのADNのソートやフィルタリング改善する方法を調査しています

  • ダイナミックな列を持ち、潜在的にセルごとに複数の値を持つ多数の行のページングは​​、どのようにして最適な方法になりますか?

現在、私たちはPostgreSQLを使用していますが、可能であればそれを使い続けたいと思いますが、別のストレージがはるかに適している場合は、少なくともチェックしてください。

(下部)アプローチと質問(複数可)現在

前述したように、私たちは現在、データベースのソート、フィルタを持っており、我々のデータをページ付けしようとしています。 2つのクエリを使用しても問題ありません.1つは現在のページの行IDを取得するクエリであり、もう1つは実際にそれらの行のデータを読み込むクエリです。

挑戦は、私はそれに集中します最初のクエリがあるので:理論このクエリでは

SELECT DISTINCT id FROM (
    SELECT id, ... FROM car c 
    LEFT OUTER JOIN allowedtyresizes ats ON c.id = ats.car_id 
    LEFT OUTER JOIN tyresizes ts ON ts.id = ats.tyresize_id 
    ... //additional joins if required 
    ORDER BY ... //apply any user-defined sorts 
    WHERE ... //apply any user-defined filters (or maybe put them into the joins) 
) 
    OFFSET ... //page offset 
    LIMIT ... //page size 

:我々はSQLでこのような何か(上の車の例を使用)を行うことができ

私の知る限り(それは完全ではないかもしれませんが)現在のページにロードする行を特定するために必要な結果を提供する必要があります。

私たちはHibernate(5.2 atm)を使用しているので、これを達成するためにHQLまたはCriteriaを使用したいと思います。しかし、Hibernateが上記のようなselectステートメントからの選択をサポートしていないかのように見えます。したがって、実行可能なアプローチではないかもしれません。ネイティブSQLや全く異なるアプローチに落ちなければならない場合は、現在のインフラストラクチャと連携させることをお勧めします。

だから、質問は以下のとおりです。

  • は、「選択から選択して」のような5.xのサポート何かを休止していますか?
  • ソートとフィルタリングを多対多リレーションシップで行う必要がある場合、つまり、単一のジョインで重複行が発生する可能性がある場合、Hibernateを使用するページネーションはどのように行われますか?
+0

HQLを使用してクエリを渡すことで、クエリを実行します。 –

+0

@GauravSrivastavはい、私たちはSQLクエリの実行方法を知っています。しかし、クエリが非常に複雑になり、動的に作成されるため、Hibernateが既に使用できるものを提供しているのではなく、そのようなクエリを構築するために必要な情報を抽出するために、 – Thomas

+0

あなたのモデルはどれくらい複雑ですか?データベースビューを使用してエンティティをバインドすることで、おそらく最高のパフォーマンスが得られます。悪い点は、データベースビュー(新しいRDBMSのサポートを開始する場合は別のバージョン)を手作業で書く必要があることです。良いことは、エンティティがよりシンプルになり、Hibernateがパフォーマンスの低いSQLを生成する機会が少なくなることです。 –

答えて

2

私は過去の雇用主に同様の要件がありましたが、私たちは同様に小規模なデータセットではデータベースがそれ以上の能力を持っていることに気付きました。ただし、データベースでさえ危機にさらされるような転機があります。

私の解決策は、Hibernate SearchとElasticSearchとの統合を導入して、NoSQL Luceneデータストアに検索データを格納することでした。これは、前述したように、ユニコードベースのテキストクエリと並べ替えでは絶対に高速です。

これにより、既存のHibernate ORMインフラストラクチャを引き続き使用して、これらの追加コンポーネントを最小限の労力でアーキテクチャに組み込むことができます。統合はシームレスで、特にデータセットが時間とともに成長し続ける中で、投資価値があります。

私たちは10億の行で作業していましたが、パフォーマンス上の問題は全くありませんでした。並べ替えとページングを行うクエリでは、平均して100ミリ秒未満でした。

+0

Thx実際には、Elasticの代わりにLucenceが直接使用されているだけで、Hibernate Searchは既にその場所にあります。 Elasticはパフォーマンスをさらに向上させるか、データに簡単にアクセスできるようにするか?更新をどのように処理しますか?変更されたドキュメント全体または変更されたフィールドのみを更新しますか?私は更新プログラムが非同期的に処理されると推測します。 – Thomas

+1

Luceneをアプリケーションに直接埋め込むよりも、インデックスがマイクロサービスアーキテクチャの多くでホストされているため、ESを使いやすくなっています。また、マスタ/スレーブ間のインデックスレプリケーションにいくつかの問題があり、代わりにESを使用するようになりました。更新に関しては、今日Luceneに複製されているように、ESに複製されます。私は更新が非同期ではなく、HibernateがSearchが聴いているさまざまなイベントを発生させるときに起こると信じています。 – Naros

+0

Afaik Hibernate Searchは、トランザクションの最後にアップデートをトリガーします。したがって、デフォルトでは基本的に同期しています。しかし、大規模なトランザクションで毎回第1レベルのキャッシュをクリアする必要があり、その結果HSが分離されたエンティティを詰まらせてしまった場合、(別のプロジェクトで)これにいくつか問題が発生しました。したがって私はそこにいくつかの非同期更新を導入しました。したがって、私の質問(非同期更新は、ES/Luceneが利用できない場合でもトランザクションのロールバックのリスクを減らすでしょう)。 – Thomas

関連する問題