説明
この式は、全文インデックスに対してテキスト検索を行うために使用されます。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を計算する際、クエリにLIMITが含まれている場合、OceanBaseデータベースはパフォーマンスを向上させるために、トップ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