0

マルチテナント Web アプリケーションを開発しており、全文検索を追加して、次のことができるようにしたいと考えています。

1) 現在アクセスしているサイトのみを検索する (ただし、すべてのサイトではない)、
2) そのサイトのセクションのみを検索する (たとえば、サイトのブログまたはフォーラムに検索を制限する)、および
3) 単一のフォーラム スレッドを検索するそれだけ。

どのインデックスを追加すればよいのでしょうか?

データベースが巨大であると仮定してください (そのため、たとえば、サイト ID によるインデックス スキャンと、全文検索によるフィルタリングが遅すぎるため)。

次の 3 つのアプローチが考えられます。

  1. 3 つのインデックスを作成します。1) サイトごとにすべてをインデックス化するもの。そして 2) サイトごととサイト セクションごとにすべてのインデックスを作成するもの。3) サイトおよびページ ID ごとにすべてをインデックス化するもの。

  2. 1 つのインデックスを作成し、[インデックスするテキスト] に「site_<site-id>」、「section_<section-id>」、「page_<page-id>」などのマジック ワードを挿入します。サイト YYY のセクション XX の場合、「site_XX AND section_YYY AND ...」のように検索クエリの前に付けることができます。

  3. 新しいサイトまたはサイト セクションの作成時にデータベース インデックスを動的に追加します。

     create index dw1_posts__search_site_YYY
       on dw1_posts using gin(to_tsvector('english', approved_text))
       where site_id = 'YYY';
    

上記の 3 つのアプローチのいずれかが理にかなっていますか? より良い代替手段はありますか?


(詳細: ただし、アプローチ 1 はおそらく不可能ですか? 列のインデックス作成と全文検索のインデックス作成を同時に試みると、構文エラーが発生します。

> create index dw1_posts__search_site
    on dw1_posts (site_id)
    using gin(to_tsvector('english', approved_text));
ERROR:  syntax error at or near "using"
LINE 1: ...dex dw1_posts__search_site on dw1_posts(site_id) using gin(...
                                                             ^

> create index dw1_posts__search_site
    on dw1_posts
    using gin(to_tsvector('english', approved_text))
    (site_id);
ERROR:  syntax error at or near "("
LINE 1: ... using gin(to_tsvector('english', approved_text)) (site_id);

(アプローチ 1可能であれば、次のようなクエリを実行できます。

select ... from ... where site_id = ... and <full-text-search-column> @@ <query>;

PostgreSQL に最初に site_id をチェックさせ、次に 1 つのインデックスを使用して全文検索列をチェックさせます。) )
/ 詳細の終了。)


更新、1 週間後:代わりにElasticSearchを使用しています。リレーショナル データベース / PostgreSQL では、ファセット検索のスケーラブルなソリューションが存在しないという印象を受けました。また、ElasticSearch との統合は、ここで提案されているアプローチを実装してテストし、微調整するのとほぼ同じくらい簡単なようです。(たとえば、PostgreSQL のステマー/それが何であれ、"section_NNN" を "section" と "NNN" の 2 つの単語に分割し、ページに存在しない単語をインデックス化する可能性があります! このような小さな迷惑な問題を修正するのは難しいです。)

4

2 に答える 2

1

通常のアプローチは、次のものを作成することです。

  • 1 つの全文索引:

    gin(to_tsvector('english', approval_text)); を使用して dw1_posts にインデックス idx1 を作成します。

  • site_id の単純なインデックス:

    dw1_posts(page_id) にインデックス idx2 を作成します。

  • page_id の別の単純なインデックス:

    dw1_posts(site_id) にインデックス idx3 を作成します。

次に、クエリと列内の値の分布に応じて、使用するものとその順序を決定するのは、SQL プランナーの仕事です。遅いクエリを実際に目にする前に、プランナーの裏をかこうとしても意味がありません。

于 2013-07-13T17:30:38.953 に答える
0

"site_<site-id>" と "section_<section-id>" と "page_<page-id>" の代替案に似た別の代替案は、インデックスを作成するテキストの前に次のようにする必要があります。

SiteSectionPage_<site-id>_<section-id>_<subsection-id>_<page-id>

そして、検索時にプレフィックス マッチング (つまり:*)を使用します。

select ... from .. where .. @@ 'SiteSectionPage_NN_MMM:* AND (the search phrase)'

ここで、NN はサイト ID、MMM はセクション ID です。

しかし、これは中国語ではうまくいきませんか?中国語のインデックスを作成するときはトライグラムが適切だと思いますが、SiteSectionPage... はSit、ite、teS、eSe に分割され、意味がありません。

于 2013-07-14T03:34:43.673 に答える