問題
このタスクは、インデックスを利用できない限りO(N²)問題であるため、重要なサイズのテーブルに対してデータベース サーバーを停止させる可能性があります。
シーケンシャル スキャンでは、2 つの行のすべての可能な組み合わせ、つまり組み合わせをチェックする必要があります。逆の重複した組み合わせを除外するのは簡単ではないため、n * (n-1) / 2
Postgres はテストを実行します。n * n-1
最初の試合に満足すれば、安くなります - いくらになるかは、データの配布によって異なります。多くの一致の場合、Postgres は行の一致を早期に見つけ、残りのテストをスキップできます。いくつかの一致については、ほとんどのチェックをとにかく実行する必要があります。
いずれにせよ、パフォーマンスはテーブル内の行数とともに急速に低下します。EXPLAIN ANALYZE
テーブル内の 10、100、1000 などの行で各クエリをテストして、自分で確認してください。
解決
できればGINにトライグラム インデックスを作成します。word
CREATE INDEX tbl_word_trgm_gin_idx ON tbl USING gin (word gin_trgm_ops);
詳細:
これまでの両方の回答のクエリは、インデックスがあったとしてもそれを使用しません。このインデックスで実際に機能するクエリを使用します。
すべての一致を一覧表示するには (質問の本文に従って): 次
を使用しLATERAL CROSS JOIN
ます。
SELECT t2.word_id, t2.word, t1.word_id, t1.word
FROM tbl t1
, LATERAL (
SELECT word_id, word
FROM tbl
WHERE word_id <> t1.word_id
AND word like format('%%%s%%', t1.word)
) t2;
(タイトルに従って)一致する行を取得するEXISTS
には:半結合を使用します:
SELECT t1.word_id, t1.word
FROM tbl t1
WHERE EXISTS (
SELECT 1
FROM tbl
WHERE word_id <> t1.word_id
AND word like format('%%%s%%', t1.word)
);