説明
この式は、全文インデックス上でテキスト検索を行うために使用されます。AGAINST は検索文字列を受け取り、文字セットの比較方法に従ってインデックス内で検索を実行します。テーブル内の各行データについて、MATCH の戻り値は検索文字列と行内データの関連度、すなわち検索文字列のテキストとデータテーブル内のテキストの類似度を表します。
構文
MATCH (column_set) AGAINST (query_expr [mode_flag])
column_set:
column_name [, column_name ...]
mode_flag:
IN NATURAL LANGUAGE MODE
| IN BOOLEAN MODE
| IN MATCH PHRASE MODE
パラメータの説明
フィールド |
説明 |
|---|---|
| column_set | 全文検索を行う列を指定します。複数の列を指定する場合は、列の間に半角カンマを区切ります。クエリは列の順序に関係ありません。column_set と完全に一致する全文インデックスが存在しなければ、対応する MATCH AGAINST 式を実行することはできません。 |
| query_expr | 検索するキーワードまたはフレーズ、つまりマッチングするパラメータを指定します。OceanBaseデータベースは、マッチングした全文インデックスで使用されている分かち書きツールを使用して query_expr を分かち書きし、その後全文インデックス上で検索を実行します。 |
| mode_flag | オプションです。全文検索のモードを表します。デフォルト値は IN NATURAL LANGUAGE MODE です。詳細については、以下の mode_flag を参照してください。 |
mode_flag
IN NATURAL LANGUAGE MODE:デフォルト値です。自然言語検索モードを使用して検索を行うことを指定します。このモードの全文検索は、クエリ式(query_expr)を分かち書いて得られた単語(token)の集合と、インデックス内の単語(token)とのマッチングによって検索を行います。クエリ式内の単語とインデックス内の単語のいずれか一つでもマッチングに成功すれば、マッチング成功と見なされます。同時に、単語頻度に基づく方法(Okapi BM25)を用いて、マッチングに成功した行の関連性をランキング(ソート)します。デフォルト設定、または
IN NATURAL LANGUAGE MODE指示子を指定した場合、MATCH AGAINSTはNATURAL LANGUAGEモードで全文検索を行います。NATURAL LANGUAGEモードでは、AGAINSTは検索文字列を受け取り、文字セットの比較方法に従ってインデックス内で検索を実行します。テーブル内の各行データについて、MATCHの戻り値は検索文字列と行内データの関連度、すなわち検索文字列のテキストとデータテーブル内のテキストの類似度を表します。IN BOOLEAN MODE:ブールモードを使用して検索を行うことを指定します。現在のバージョンでは、3つの最も一般的なブール演算子と、演算子のネストをサポートしています。具体的には以下の通りです:+:AND、すなわち共通部分を表します。-:否定、すなわち差集合を表します。無操作記号:単独で使用すると
OR、すなわち和集合を表します。例えばA BはA OR Bを表します。和記号と混在させると、存在する文の関連性を高めますが、ORの意味を失います。例えば+A Bの場合、A が必要であり、文中の A と B の関連性を計算することを意味します。():演算子のネストを表します。外側に記号がない場合、ORの意味を持ちます。例えば+A (ネストされた句)は、A が必要であるか、ネストされた句が必要であることを表します。説明
OceanBaseデータベースV4.3.5では、V4.3.5 BP1から
IN BOOLEAN MODEがサポートされています。例:
出力される文には必ず computer が含まれている必要があります。
SELECT * FROM my_table WHERE MATCH (doc) AGAINST ("+computer" IN BOOLEAN MODE);出力される文には必ず computer が含まれており、weather は含まれていない必要があります。
SELECT * FROM my_table WHERE MATCH (doc) AGAINST ("+computer -weather" IN BOOLEAN MODE);出力される文には必ず computer が含まれており、oceanbase が含まれている方がよりマッチします。
SELECT * FROM my_table WHERE MATCH (doc) AGAINST ("+computer oceanbase" IN BOOLEAN MODE);
IN MATCH PHRASE MODE:正確なフレーズマッチングをサポートします。説明
OceanBaseデータベースは、バージョンV4.4.0から
IN MATCH PHRASE MODEをサポートしています。例:
テーブルtestを作成し、指定された列に全文インデックスを追加します。
CREATE TABLE test(c1 int, c2 VARCHAR(200), c3 TEXT, FULLTEXT INDEX fts_idx (c2, c3));c2、c3列で
some wordsと完全一致するレコードを検索します。SELECT c2 FROM test WHERE MATCH(c2,c3) AGAINST('some words' IN MATCH PHRASE MODE);
使用方法
MATCH AGAINST 式は、テキストマッチングを表すだけでなく、SQLのさまざまな句で使用される場合、他の意味も含みます:
プロジェクションの相関性:
- 全文検索は、単語頻度に基づくランキングをサポートしており、MATCH AGAINST 式を使用して相関性のプロジェクションを表現できます。
- 相関性とは、マッチしたデータ行とMATCH AGAINSTのクエリ(Query)との関連度を示します。
- 相関性は0以上の
DOUBLE型データであり、0はデータ行がクエリ(Query)と無関係であることを意味し、数値が大きいほど相関性が強いことを示します。
フィルタリングの意味:
WHERE句に現れるMATCH AGAINST式が、他のすべてのフィルタ条件とANDで結合されている場合、フィルタリングの意味を含み、一致しないデータ行を除外します。例:
SELECT id, digest, detail FROM t1 WHERE MATCH (detail) AGAINST ('oceanbase');これは次のものと等価です:
SELECT id, digest, detail FROM t1 WHERE MATCH (detail) AGAINST ('oceanbase') > 0;
ソートの意味:
WHERE句内で他のフィルタ条件とANDで結合されたMATCH AGAINST式には、ソートの意味が含まれます。- 全文検索の結果を
MATCH AGAINSTの相関ランキングの降順で並べ替えることを示します。 - 複数の
MATCH AGAINST式が存在する場合、最初のMATCH AGAINSTの相関性でソートされます。
例:
SELECT id, digest, MATCH (detail) AGAINST ('oceanbase') AS relevance FROM t1 WHERE MATCH (detail) against ('oceanbase');これは、次のものと等価です。
SELECT id, digest, MATCH (detail) AGAINST ('oceanbase') AS relevance FROM t1 WHERE MATCH (detail) AGAINST ('oceanbase') ORDER BY relevance DESC;
テキスト検索の実行方式
SQLの
MATCH AGAINSTにフィルタリングの意味が含まれる場合、OceanBaseデータベースは全文インデックスをスキャンしてMATCH AGAINST式を計算し、その後テーブルに戻ってクエリを実行します。SQLの
MATCH AGAINSTにフィルタリングの意味が含まれない場合、OceanBaseデータベースは他のセカンダリインデックスを使用してスキャンとフィルタリングをサポートし、主キーに基づいてランダムに全文インデックスにアクセスしてMATCH AGAINST式を計算し、クエリを実行します。SQLの
WHERE句にMATCH AGAINSTとANDで結合された複数のフィルタ条件が含まれ、かつ他のセカンダリインデックスにヒットする可能性がある場合、OceanBaseデータベースはコストに基づいて適切なインデックスを選択してスキャンを試みます。全文インデックスをスキャンして
MATCH AGAINSTを計算する際、QueryにLIMITが含まれる場合、OceanBaseデータベースはパフォーマンスを向上させるために、top-kの計算を全文インデックスのスキャン中にオフロードして実行しようと試みます。クエリに
ORで結合されたMATCH AGAINST句が含まれる場合、自動的にIndex Mergeプランの生成が試みられます。最終的にIndex Mergeプランが採用されるかどうかは、コスト競争の結果によります。説明
- V4.4.1バージョン以降、Index Mergeプランは
ANDで結合された複数の述語をサポートしています。クエリにMATCH AGAINSTを含む複数の述語が含まれる場合、自動的にIndex Mergeプランが生成されます。 - V4.4.1以前のバージョンでは、Index Mergeプランは
ORで結合された複数の述語のみをサポートしていました。
- V4.4.1バージョン以降、Index Mergeプランは
例
サンプルテーブル
test_tbl1を作成し、全文インデックスft_idx1_test_tbl1とft_idx1_test_tbl1、およびインデックスidx_test_tbl1を作成します。CREATE TABLE test_tbl1(id INT, ref_no INT, digest VARCHAR(512), detail VARCHAR(4096), FULLTEXT INDEX ft_idx1_test_tbl1(detail), FULLTEXT INDEX ft_idx2_test_tbl1(digest, detail), INDEX idx_test_tbl1 (id));テーブル
test_tbl1にテストデータを挿入します。INSERT INTO test_tbl1 VALUES (1, 1234, 'fulltext', 'Try text retrieval with OceanBase fulltext index'), (2, 2345, 'log', 'OceanBase can halp with log analysis'), (3, 3456, 'order', 'Simple text retrieval scan will return result set in order of descending ranking in OceanBase'), (4, 4567, 'ranking', 'OceanBase will ranking relevance to query for matched result set'), (5, 5678, 'filter', 'Using text retrieval as a filter condition would be probably more efficient');MATCH AGAINST式を使用して関連性を投影します。SELECT id, digest, detail, MATCH (detail) AGAINST ('oceanbase') AS relevance FROM test_tbl1;実行結果は次のとおりです:
+------+----------+-----------------------------------------------------------------------------------------------+--------------------+ | id | digest | detail | relevance | +------+----------+-----------------------------------------------------------------------------------------------+--------------------+ | 1 | fulltext | Try text retrieval with OceanBase fulltext index | 0.2989130434782609 | | 2 | log | OceanBase can halp with log analysis | 0.3142857142857143 | | 3 | order | Simple text retrieval scan will return result set in order of descending ranking in OceanBase | 0.240174672489083 | | 4 | ranking | OceanBase will ranking relevance to query for matched result set | 0.2849740932642488 | | 5 | filter | Using text retrieval as a filter condition would be probably more efficient | 0 | +------+----------+-----------------------------------------------------------------------------------------------+--------------------+ 5 rows in setMATCH AGAINST式を使用してフィルタリングを行います。SELECT id, digest, detail FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase');実行結果は次のとおりです:
+------+----------+-----------------------------------------------------------------------------------------------+ | id | digest | detail | +------+----------+-----------------------------------------------------------------------------------------------+ | 2 | log | OceanBase can halp with log analysis | | 1 | fulltext | Try text retrieval with OceanBase fulltext index | | 4 | ranking | OceanBase will ranking relevance to query for matched result set | | 3 | order | Simple text retrieval scan will return result set in order of descending ranking in OceanBase | +------+----------+-----------------------------------------------------------------------------------------------+ 4 rows in setMATCH AGAINST式を使用して検索とソートを行います。SELECT id, digest, MATCH (detail) AGAINST ('oceanbase') AS relevance FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase');または
SELECT id, digest, MATCH (detail) AGAINST ('oceanbase') AS relevance FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase') ORDER BY relevance DESC;実行結果は次のとおりです:
+------+----------+--------------------+ | id | digest | relevance | +------+----------+--------------------+ | 2 | log | 0.3142857142857143 | | 1 | fulltext | 0.2989130434782609 | | 4 | ranking | 0.2849740932642488 | | 3 | order | 0.240174672489083 | +------+----------+--------------------+ 4 rows in set
テキスト検索実行計画の例
MATCH AGAINSTにはフィルタリングの意味が含まれており、全文インデックスft_idx1_test_tbl1でスキャンされます。EXPLAIN SELECT id, digest, detail FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase') AND id = 3;実行結果は次のとおりです:
+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ============================================================================= | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | ----------------------------------------------------------------------------- | | |0 |SORT | |1 |30 | | | |1 |└─TEXT RETRIEVAL SCAN|test_tbl1(ft_idx1_test_tbl1)|1 |30 | | | ============================================================================= | | Outputs & filters: | | ------------------------------------- | | 0 - output([test_tbl1.id], [test_tbl1.digest], [test_tbl1.detail]), filter(nil), rowset=16 | | sort_keys([MATCH(test_tbl1.detail) AGAINST('oceanbase'), DESC]) | | 1 - output([test_tbl1.detail], [test_tbl1.id], [test_tbl1.digest], [MATCH(test_tbl1.detail) AGAINST('oceanbase')]), filter([test_tbl1.id = 3]), rowset=16 | | access([test_tbl1.__pk_increment], [test_tbl1.detail], [test_tbl1.id], [test_tbl1.digest]), partitions(p0) | | is_index_back=true, is_global_index=false, filter_before_indexback[false], | | calc_relevance=true, match_expr(MATCH(test_tbl1.detail) AGAINST('oceanbase')), | | pushdown_match_filter(MATCH(test_tbl1.detail) AGAINST('oceanbase')) | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ 15 rows in setMATCH AGAINSTにはフィルタリングの意味が含まれていますが、通常のセカンダリインデックスidx_test_tbl1がヒットし、かつidx_test_tbl1インデックスのスキャンコストが低いため、インデックスidx_test_tbl1でスキャンされます。EXPLAIN SELECT id FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase simple text retreival scan on fulltext index') AND id = 3;実行結果は次のとおりです:
+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ====================================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | ---------------------------------------------------------------------- | | |0 |SORT | |1 |103 | | | |1 |└─TABLE RANGE SCAN|test_tbl1(idx_test_tbl1)|1 |103 | | | ====================================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output([test_tbl1.id]), filter(nil), rowset=16 | | sort_keys([MATCH(test_tbl1.detail) AGAINST('oceanbase simple text retreival scan on fulltext index'), DESC]) | | 1 - output([test_tbl1.id], [MATCH(test_tbl1.detail) AGAINST('oceanbase simple text retreival scan on fulltext index')]), filter([MATCH(test_tbl1.detail) | | AGAINST('oceanbase simple text retreival scan on fulltext index')]), rowset=16 | | access([test_tbl1.__pk_increment], [test_tbl1.id]), partitions(p0) | | is_index_back=false, is_global_index=false, filter_before_indexback[false], | | range_key([test_tbl1.id], [test_tbl1.__pk_increment]), range(3,MIN ; 3,MAX), | | range_cond([test_tbl1.id = 3]), has_functional_lookup=true | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ 16 rows in setMATCH AGAINSTにはフィルタリングの意味合いが含まれていないため、結果セットをフィルタリングしたり、全文インデックスでスキャンしたりすることはできません。メインテーブルをスキャンします。EXPLAIN SELECT id, digest, detail FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase') OR id = 3;実行結果は次のとおりです:
+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ==================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | ---------------------------------------------------- | | |0 |TABLE FULL SCAN|test_tbl1|5 |503 | | | ==================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output([test_tbl1.id], [test_tbl1.digest], [test_tbl1.detail]), filter([MATCH(test_tbl1.detail) AGAINST('oceanbase') OR test_tbl1.id = 3]), rowset=16 | | access([test_tbl1.__pk_increment], [test_tbl1.detail], [test_tbl1.id], [test_tbl1.digest]), partitions(p0) | | is_index_back=false, is_global_index=false, filter_before_indexback[false], | | range_key([test_tbl1.__pk_increment]), range(MIN ; MAX)always true, has_functional_lookup=true | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ 11 rows in setMATCH AGAINSTにはフィルタリングの意味合いが含まれていないため、結果セットをフィルタリングしたり、全文インデックスでスキャンしたりすることはできません。インデックスidx_test_tbl1にヒットし、インデックスidx_test_tbl1をスキャンします。EXPLAIN SELECT id FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase') OR id = 3;実行結果は次のとおりです:
+------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +------------------------------------------------------------------------------------------------------------------------------+ | =================================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | ------------------------------------------------------------------- | | |0 |TABLE FULL SCAN|test_tbl1(idx_test_tbl1)|5 |503 | | | =================================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output([test_tbl1.id]), filter([MATCH(test_tbl1.detail) AGAINST('oceanbase') OR test_tbl1.id = 3]), rowset=16 | | access([test_tbl1.__pk_increment], [test_tbl1.id]), partitions(p0) | | is_index_back=false, is_global_index=false, filter_before_indexback[false], | | range_key([test_tbl1.id], [test_tbl1.__pk_increment]), range(MIN,MIN ; MAX,MAX)always true, has_functional_lookup=true | +------------------------------------------------------------------------------------------------------------------------------+ 11 rows in setMATCH AGAINSTにはフィルタリングの意味合いが含まれており、対応する全文インデックスft_idx1_test_tbl1にヒットしてスキャンします。同時にLIMITがトップ k のダウンプッシュインデックススキャンとして機能します。EXPLAIN SELECT id, digest, detail FROM test_tbl1 WHERE MATCH (detail) AGAINST ('oceanbase') LIMIT 3;実行結果は次のとおりです:
+------------------------------------------------------------------------------------------------------------------+ | Query Plan | +------------------------------------------------------------------------------------------------------------------+ | =========================================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | --------------------------------------------------------------------------- | | |0 |TEXT RETRIEVAL SCAN|test_tbl1(ft_idx1_test_tbl1)|4 |31 | | | =========================================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output([test_tbl1.id], [test_tbl1.digest], [test_tbl1.detail]), filter(nil), rowset=16 | | access([test_tbl1.__pk_increment], [test_tbl1.detail], [test_tbl1.id], [test_tbl1.digest]), partitions(p0) | | is_index_back=true, is_global_index=false, | | calc_relevance=true, match_expr(MATCH(test_tbl1.detail) AGAINST('oceanbase')), | | pushdown_match_filter(MATCH(test_tbl1.detail) AGAINST('oceanbase')), | | sort_keys([MATCH(test_tbl1.detail) AGAINST('oceanbase'), DESC]), limit(3), offset(nil), with_ties(false) | +------------------------------------------------------------------------------------------------------------------+ 13 rows in set