2

私はWeb上にデプロイされているアプリケーションに取り組んでいます。アプリの一部は、結果がソートされたリストに表示される検索機能です。このアプリケーションは、さまざまなロケール(=並べ替えルール)を使用して、いくつかの国のユーザーを対象としています。すべてのユーザーを正しく並べ替えるための解決策を見つける必要があります。

現在、SQLクエリでORDER BYを使用して並べ替えているため、データベースに設定されているロケール(またはLC_LOCATE)に従って並べ替えが行われます。これらのルールは、データベースに設定されているロケールとは異なるロケールを持つユーザーには正しくありません。

また、問題をさらに複雑にするために、アプリケーションでページ付けを使用しているため、データベースにクエリを実行するときに、必要なページに応じて1〜15、16〜30行などを要求します。ただし、並べ替えが間違っているため、各ページには誤って並べ替えられたエントリが含まれています。最悪のシナリオでは、現在のユーザーのロケール/並べ替えルールによっては、特定のページの結果セット全体が乱れる可能性があります。

(サーバー側の)コードを並べ替える場合は、データベースからすべての行を取得してから並べ替える必要があります。これにより、データ量を考えると、パフォーマンスが大幅に低下します。したがって、私はこれを避けたいと思います。

すべてのデータをロードするというパフォーマンスの打撃を受けることなく、正しくソートされたリストをもたらすこの問題を攻撃するための戦略(または技術的な解決策)を持っている人はいますか?

技術的な詳細:データベースはPostgreSQL 8.3であり、アプリケーションはデータクエリにEJB QLを使用するEJB3アプリであり、JBoss4.5で実行されます。

4

5 に答える 5

2

C で小さな Postgres カスタム関数モジュールを開発する意思はありますか? (経験豊富な C コーダーの場合、おそらく数日しかかかりません。)

strxfrm()は、現在の LC_COLLATE 設定 (多かれ少なかれ現在の言語) に基づいて言語依存のテキスト文字列を変換された文字列に変換する関数です。変換された文字列は、バイナリ バイト シーケンス (例: strcmp()) として並べ替えると、その言語で適切な照合順序になります。

これをPostgresに実装すると、たとえば文字列と照合順序を取ると、strxfrm(textfield, collat​​ion_order) で順序付けできるようになります。オプティマイザーがインデックスを使用するように、その関数を使用して strxfrm() の結果を格納することで、テキスト列に複数の関数インデックス (言語ごとに 1 つなど) を作成することもできると思います。

または、Postgres 開発者と協力して、主流の Postgres でこれを実装することもできます。この問題に関する wiki ページは次のとおりです: Collat​​ionICU (私の知る限り Java でも使用されています)。


または、データ入力が Java のみである場合のあまり洗練されていない解決策として、データをデータベースに追加するときに Java でこれらの strxfrm() 値を計算することができます (Java はおそらくこの概念に別の名前を付けます)。これらの事前計算された値によるインデックスと順序付け。

于 2010-01-21T00:07:25.527 に答える
0

PostgreSQLとどの程度結びついていますか?ドキュメントは有望ではありません:

一部のロケールカテゴリの性質は、データベースクラスタの存続期間中、それらの値を固定する必要があることです。つまり、initdbが実行されると、それらを変更することはできなくなります。LC_COLLATELC_CTYPEはそれらのカテゴリです。これらはインデックスの並べ替え順序に影響するため、固定しておく必要があります。そうしないと、テキスト列のインデックスが破損します。PostgreSQLは、initdbによって表示されるLC_COLLATEとの値を記録することでこれを強制します。LC_CTYPEサーバーは、起動時にこれら2つの値を自動的に採用します。

(照合規則は、テキストの並べ替え方法を定義します。)

グーグルは議論中のパッチを投げます:

PostgreSQLは現在、データベースクラスターの初期化時にLC_COLLATE変数によって修正されるため、一度に1つの照合のみをサポートします。

これをデータベースの外部で管理したいかどうかはわかりませんが、どのように実行できるかについては興味があります。(問題の技術的な概要が必要な場合は、OracleグローバリゼーションサイトのOracleデータベース内の言語データの並べ替えを確認してください。)

于 2009-08-20T16:34:08.163 に答える
0

このパッケージをチェックアウトすることをお勧めします: http://www.fi.muni.cz/~adelton/l10n/postgresql-nls-string/ . 長い間更新されておらず、もう機能しない可能性がありますが、これを実行できる関数を構築したい場合は、妥当な出発点のように思えます。

于 2010-01-21T08:50:13.097 に答える
0

order byデータベースの順序を切り替える方法がわかりません。したがって、他の解決策を検討する必要があります。

結果の数が非常に多い場合 (数十万?)、結果の数だけを表示し、ユーザーにもっと正確なリクエストを行うように求める以外に解決策はありません。それ以外の場合は、正確な条件に応じて、サーバー側で行うことができます....

特に、キャッシュを使用すると、物事が大幅に改善される可能性があります。データベースへの最初のリクエスト (無制限) は、結果の数が制限されたクエリよりもそれほど遅くはありません。そして、後続のリクエストははるかに高速になります。多くの場合、ページングと再ソートは複数のリクエストに対応するため、キャッシュは (数分間でも) うまく機能します。

私は技術的な解決策として EhCache を使用しています。ソートとページングは​​一緒に行われ、ソートしてからページングします。生の結果はキャッシュに記憶できます。

パフォーマンスへの影響を減らすためのヒント:

  • 結果セットのサイズに対してクエリを 1 回実行し、結果が多すぎる場合はユーザーに警告することができます (遅いクエリを確認するか、いくつかの選択フィールドを追加するように求めます)。
  • 必要な列のみを要求し、他のすべての列を解放します (通常、一部のデータはすべての結果に対してすぐには表示されませんが、たとえば、マウスを動かすと表示されます。このデータは、必要な場合にのみ遅延して要求できるため、すべての列に対して要求される列を減らすことができます結果)
  • 計算された値がある場合は、データベース列と計算された値の間の小さい方をキャッシュします
  • 複数の結果で値が繰り返されている場合は、そのデータ/列を個別に要求して (データベースから 1 回だけ取得し、それらを 1 回だけキャッシュする)、メイン要求でキー (通常は ID) のみを取得できます。
于 2009-08-20T16:58:01.360 に答える
0

このモジュールは、Postgres 8.4.3 では壊れています。私はそれを修正しました - http://www.itreport.eu/__cw_files/.01/.17/.ee7844ba6716aa36b19abbd582a31701/nls_string.cから修正バージョンをダウンロードできます。手動でコンパイルしてインストールする必要があります (関連する README と INSTALL を元のモジュールから) しかし、とにかく並べ替えが正しく機能していません。FreeBSD 8.0で試してみた、LC_COLLATEはcs_CZ.UTF-8

于 2010-05-04T21:54:34.580 に答える