すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB for SelectDB:転置インデックス

最終更新日:Jan 27, 2025

転置インデックスは、情報検索によく使用されます。テキストを term にトークン化して、転置インデックスを作成できます。これにより、指定された term を含むドキュメントをすばやく取得できます。ApsaraDB for SelectDB は転置インデックスをサポートしています。転置インデックスを使用して、TEXT 型のデータの全文検索、および NUMERIC 型と DATE 型のデータの等価クエリまたは範囲クエリを実行できます。この方法で、大量のデータから特定の条件を満たすデータをすばやく取得できます。このトピックでは、ApsaraDB for SelectDB の転置インデックスの特徴と、転置インデックスの作成方法と使用方法について説明します。

実装

ApsaraDB for SelectDB の転置インデックスの実装では、テーブルの各行はドキュメントに、各列はドキュメント内のフィールドに対応します。そのため、転置インデックスを使用すると、特定の term を含む行をすばやく見つけることができます。これは、WHERE 句を含むクエリの高速化に役立ちます。

転置インデックスは、ApsaraDB for SelectDB の他のインデックスとは異なります。 ApsaraDB for SelectDB は、転置インデックスを格納するために別のファイルを使用します。別のファイルはセグメントファイルと論理マッピングされていますが、2 つのファイルは互いに独立しています。これにより、転置インデックスを更新および削除するときにセグメントファイルを書き直す必要がなくなり、処理のオーバーヘッドが大幅に削減されます。

シナリオ

  • STRING 型のデータの全文検索を高速化したい場合。

  • 次の演算子を使用して、STRING、NUMERIC、または DATETIME 型のデータの検索を高速化したい場合: =, !=, >, >=, <, and <=

メリット

  • 論理結合をサポート。

    • OR 演算子と NOT 演算子のインデックスフィルタープッシュダウンをサポート。

    • AND、OR、および NOT 演算子の組み合わせをサポート。

  • インデックスの柔軟で迅速な管理をサポート。

    • テーブルの作成時に転置インデックスを作成できます。

    • 既存のテーブルに転置インデックスを作成できます。

    • テーブルから既存の転置インデックスを削除できます。

制限事項

  • 高精度ではない FLOAT データ型と DOUBLE データ型は、転置インデックスをサポートしていません。DECIMAL データ型は高精度であり、転置インデックスをサポートしています。DECIMAL 型を使用できます。

  • 一部の複合データ型は、転置インデックスをサポートしていません。複合データ型には、MAP、STRUCT、JSON、HLL、BITMAP、QUANTILE_STATE、および AGG_STATE が含まれます。JSON データ型は、VARIANT データ型に変換された後に転置インデックスをサポートできます。

  • NUMERIC 型のフィールドは転置インデックスをサポートしていますが、フィールドにパーサーを指定することはできません。パーサーの有効な値: english、chinese、unicode。

  • Merge on Write(MoW)が有効になっている DUPLICATE モデルと UNIQUE モデルの任意の列に転置インデックスを作成できます。MoW が無効になっている AGGREGATE モデルと UNIQUE モデルのキー列にのみ転置インデックスを作成できます。モデルの他の列に転置インデックスを作成できます。モデルはすべてのデータを読み取ってマージする必要があります。したがって、インデックスを使用して事前にデータをフィルタリングすることはできません。

転置インデックスを作成する

テーブルの作成時に転置インデックスを作成するか、既存のテーブルの列に転置インデックスを作成できます。

テーブルの作成時に転置インデックスを作成する

この操作は同期操作です。テーブルの作成時に転置インデックスを作成すると、テーブルと転置インデックスが同期的に作成されます。

重要

転置インデックスには、次のデータモデルで異なる制限があります。

  • Aggregate キーモデルでは、キー列にのみ転置インデックスを作成できます。

  • Unique キーモデルでは、MoW 機能を有効にする必要があります。MoW 機能を有効にすると、任意の列に転置インデックスを作成できます。

  • Duplicate キーモデルでは、任意の列に転置インデックスを作成できます。

構文

CREATE TABLE  [IF NOT EXISTS] [db_name.]<table_name>
(
  <column_definition_list>,
  [<index_definition_list>] 
)
table_properties;

パラメーター

テーブルの作成に使用されるパラメーター

パラメーター

必須

説明

db_name

いいえ

テーブルを作成するデータベースの名前。

table_name

はい

作成するテーブルの名前。

column_definition_list

はい

列定義のリスト。詳細については、「CREATE-TABLE」をご参照ください。

table_properties

はい

データモデル、パーティション設定、バケット設定など、テーブルのプロパティ。詳細については、「データモデル」をご参照ください。

index_definition_list

いいえ

インデックス定義のリスト。

index_definition_list

テーブルの作成時に、次の形式で複数のインデックスを定義できます: index_definition[, index_definition][, index_definition]....

index_definition の構文

INDEX <index_name>(<column_name>) <index_type> [PROPERTIES("<key>" = "<value>")] [COMMENT '<comment>']

index_definition のパラメーター

必須パラメーター

パラメーター

説明

index_name

インデックスの名前。

column_name

インデックスが作成される列の名前。

index_type

インデックスの型。USING INVERTED に設定します。

オプションパラメーター
PROPERTIES

PROPERTIES パラメーターは、インデックスに基づいてテキストを term にトークン化するかどうかを指定します。PROPERTIES パラメーターの値は、コンマ(,)で区切られた 1 つ以上のキーと値のペアで構成されます。各キーと値のペアは、"<key>" = "<value>" の形式です。連続テキストのトークン化結果を表示するには、TOKENIZE 関数を呼び出すことができます。詳細については、「TOKENIZE 関数」をご参照ください。

key

value

parser

トークナイザー。デフォルトでは、キーは空のままです。これは、テキストが term にトークン化されないことを指定します。NUMERIC 型のフィールドにパーサーを指定することはできません。有効な値:

  • english: 英語のトークナイザー。英語の term を含むフィールドに適しています。このトークナイザーは、スペースと句読点を使用してテキストを term にトークン化し、高パフォーマンスを提供します。

  • chinese: 中国語のトークナイザー。中国語の term を含むフィールドに適しています。このトークナイザーは、英語のトークナイザーよりもパフォーマンスが低くなります。

  • unicode: 混合 Unicode トークナイザー。英語と中国語の term を含むフィールドに適しています。このトークナイザーは、電子メールアドレス、IP アドレス、および文字と数字の組み合わせのプレフィックスとサフィックスをトークン化できます。また、中国語の term を文字ごとにトークン化することもできます。

parser_mode

単語トークン化モード。単語トークン化の粒度は、単語トークン化モードによって異なります。

デフォルトでは、すべてのトークナイザーに coarse_grained モードが使用されます。coarse_grained モードでは、テキストは長い term にトークン化されます。たとえば、武汉市长江大桥 は、次の 2 つの term にトークン化されます: 武汉市长江大桥

parser=chinese 設定が構成されている場合、中国語のトークナイザーが使用され、fine_grained モードがサポートされます。fine_grained モードでは、テキストは短い term にトークン化されます。たとえば、武汉市长江大桥 は、次の 6 つの term にトークン化されます: 武汉武汉市市长长江长江大桥、および 大桥

単語トークン化の使用方法の詳細については、「TOKENIZE 関数」をご参照ください。

support_phrase

インデックスを使用して MATCH_PHRASE クエリを高速化するかどうかを指定します。デフォルト値: false。

  • このパラメーターを true に設定すると、MATCH_PHRASE クエリは高速化されますが、インデックスにはより多くのストレージ容量が必要になります。

  • このパラメーターを false に設定すると、MATCH_PHRASE クエリは高速化されず、インデックスに必要なストレージスペースは少なくなります。MATCH_ALL クエリを実行して、一度に複数の term を照合できます。

char_filter

テキストが term にトークン化される前に文字列を処理するために使用されるパラメーター。char_filter_type パラメーターは char_replace のみに設定できます。

char_filter_type パラメーターを char_replace に設定すると、char_filter_pattern パラメーターの値の文字が char_filter_replacement パラメーターの値の文字に置き換えられます。

  • char_filter_pattern: 置換される文字の配列。

  • char_filter_replacement: 置換される文字を置換するために使用される文字の配列。このパラメーターは空のままにすることができます。デフォルト値はスペース文字です。

COMMENT

パラメーター

説明

comment

インデックスの説明。

-- テーブルと、comment 列に idx_comment という名前の転置インデックスを作成します。
-- USING INVERTED は、インデックスの型が転置インデックスであることを指定します。
-- PROPERTIES("parser" = "english") は、英語のトークナイザーを使用してテキストを term にトークン化することを指定します。parser パラメーターを chinese または unicode に設定することもできます。parser パラメーターを空のままにすると、テキストは term にトークン化されません。
CREATE TABLE hackernews_1m
(
    `id` BIGINT,
    `deleted` TINYINT,
    `type` String,
    `author` String,
    `timestamp` DateTimeV2,
    `comment` String,
    `dead` TINYINT,
    `parent` BIGINT,
    `poll` BIGINT,
    `children` Array<BIGINT>,
    `url` String,
    `score` INT,
    `title` String,
    `parts` Array<INT>,
    `descendants` INT,
    INDEX idx_comment (`comment`) USING INVERTED PROPERTIES("parser" = "english") COMMENT 'inverted index for comment'
)
DUPLICATE KEY(`id`)
DISTRIBUTED BY HASH(`id`) BUCKETS 10;

既存のテーブルに転置インデックスを作成する

この操作は非同期です。SHOW ALTER TABLE COLUMN; 文を実行して、インデックスの作成進捗状況をクエリできます。

構文

ALTER TABLE <table_name> ADD INDEX <index_name>(<column_name>) <index_type> [PROPERTIES("<key>" = "<value>")];

パラメーター

パラメーターは、テーブルの作成時に転置インデックスを作成するために使用されるパラメーターと同じです。

テキストを分割するために使用されない転置インデックスを作成します。

ALTER TABLE user_tb ADD INDEX index_userId(user_id) USING INVERTED ;

English トークナイザーを使用してテキストを term に分割するために使用される転置インデックスを作成します。

ALTER TABLE user_tb ADD INDEX index_city(city) USING INVERTED PROPERTIES("parser" = "english");

転置インデックスに関する情報をクエリする

インデックスの変更進捗状況をクエリする

ALTER 文または DROP 文を実行して、転置インデックスを変更できます。この操作は非同期です。次の文を実行して、変更の進捗状況をクエリできます。

SHOW ALTER TABLE COLUMN;

テーブルに作成されたすべてのインデックスをクエリする

構文

SHOW INDEXES FROM <table_name>;

SHOW INDEXES FROM user_tb;

転置インデックスを削除する

非同期モードでインデックスを削除できます。インデックスの削除進捗状況のクエリ方法の詳細については、「転置インデックスに関する情報をクエリする」をご参照ください。

重要

テーブルから転置インデックスを削除すると、テーブルに対するクエリのパーフォーマンスが低下します。注意して進めてください。

構文

-- 構文 1
DROP INDEX <index_name> ON <table_name>;
-- 構文 2
ALTER TABLE <table_name> DROP INDEX <index_name>;

DROP INDEX index_userId ON user_tb;
ALTER TABLE user_tb DROP INDEX index_city;

転置インデックスを使用する

全文検索

構文

SELECT * FROM <table_name> WHERE <column_name> <conditional_logic> '<keywords>';

パラメーター

パラメーター

必須

説明

table_name

はい

クエリするテーブルの名前。

column_name

はい

クエリする列の名前。

conditional_logic

はい

条件付きロジック。全文検索キーワードと論理演算子の組み合わせです。

論理演算子: AND、OR、NOT

全文検索キーワード:

  • MATCH_ALL: 一度に複数の term を照合します。

  • MATCH_ANY: term を照合します。

  • MATCH_PHRASE: フレーズを照合します。

keywords

はい

データをクエリするために使用される term。

複数の term はスペースで区切ります。

例: keyword1 keyword2 keyword3

-- log_tb テーブルの logmsg 列に keyword1 を含むすべての行をクエリします。
SELECT * FROM log_tb WHERE logmsg MATCH_ANY 'keyword1';

-- log_tb テーブルの logmsg 列に keyword1 または keyword2 を含むすべての行をクエリします。
SELECT * FROM log_tb WHERE logmsg MATCH_ANY 'keyword1 keyword2';

-- log_tb テーブルの logmsg 列に keyword1 と keyword2 を含むすべての行をクエリします。
SELECT * FROM log_tb WHERE logmsg MATCH_ALL 'keyword1 keyword2';

-- log_tb テーブルの logmsg 列に keyword1 と keyword2 を含み、keyword2 が keyword1 の後にあるすべての行をクエリします。
SELECT * FROM log_tb WHERE logmsg MATCH_PHRASE 'keyword1 keyword2';ログテーブル

NUMERIC 型と DATE 型のデータに対する等価クエリまたは範囲クエリ

これらのシナリオでは、クエリ構文は標準 SQL 構文と同じです。

-- 等価クエリ、範囲クエリ、および IN または NOT IN 条件を含むクエリを実行します。
SELECT * FROM user_tb WHERE id = 123;
SELECT * FROM user_tb WHERE ts > '2023-01-01 00:00:00';
SELECT * FROM user_tb WHERE op_type IN ('add', 'delete');

クエリのパフォーマンスを比較する

この例では、100 万件のデータエントリを含む hackernews テーブルを使用して、転置インデックスを使用する前後のクエリのパフォーマンスを比較します。

環境の準備

手順 1: テーブルを作成する

  1. データベースを作成します。

    CREATE DATABASE test_inverted_index;
  2. 作成したデータベースに切り替えます。

    USE test_inverted_index;
  3. テーブルを作成します。

    CREATE TABLE hackernews_1m
    (
        `id` BIGINT,
        `deleted` TINYINT,
        `type` String,
        `author` String,
        `timestamp` DateTimeV2,
        `comment` String,
        `dead` TINYINT,
        `parent` BIGINT,
        `poll` BIGINT,
        `children` Array<BIGINT>,
        `url` String,
        `score` INT,
        `title` String,
        `parts` Array<INT>,
        `descendants` INT,
        INDEX idx_comment (`comment`) USING INVERTED PROPERTIES("parser" = "english") COMMENT 'inverted index for comment'
    )
    DUPLICATE KEY(`id`)
    DISTRIBUTED BY HASH(`id`) BUCKETS 10;
    -- テーブルと、comment 列に idx_comment という名前の転置インデックスを作成します。
    -- USING INVERTED は、インデックスの型が転置インデックスであることを指定します。
    -- PROPERTIES("parser" = "english") は、英語のトークナイザーを使用してテキストを term に分割することを指定します。parser パラメーターを chinese または unicode に設定することもできます。parser パラメーターを空のままにすると、テキストは term に分割されません。

手順 2: データをインポートする

作成したテーブルにデータをインポートします。

  1. データファイルをダウンロードします。

    wget https://qa-build.oss-cn-beijing.aliyuncs.com/regression/index/hacknernews_1m.csv.gz
  2. Stream Load を使用してテーブルにデータをインポートします。

    ApsaraDB for SelectDB インスタンスの [インスタンスの詳細] ページで、ApsaraDB for SelectDB インスタンスのエンドポイントとポート番号を表示できます。Stream Load の詳細については、「Stream Load を使用してデータをインポートする」をご参照ください。

    curl --location-trusted -u root: -H "compress_type:gz" -T hacknernews_1m.csv.gz  http://<host>:<port>/api/test_inverted_index/hackernews_1m/_stream_load
    {
        "TxnId": 2,
        "Label": "a8a3e802-2329-49e8-912b-04c800a461a6",
        "TwoPhaseCommit": "false",
        "Status": "Success",
        "Message": "OK",
        "NumberTotalRows": 1000000,
        "NumberLoadedRows": 1000000,
        "NumberFilteredRows": 0,
        "NumberUnselectedRows": 0,
        "LoadBytes": 130618406,
        "LoadTimeMs": 8988,
        "BeginTxnTimeMs": 23,
        "StreamLoadPutTimeMs": 113,
        "ReadDataTimeMs": 4788
        "WriteDataTimeMs": 8811,
        "CommitAndPublishTimeMs": 38
    }
  3. count() 関数を呼び出して、データがインポートされたかどうかを確認します。

    SELECT count() FROM hackernews_1m;
    +---------+
    | count() |
    +---------+
    | 1000000 |
    +---------+
    1 row in set (0.02 sec)

パフォーマンスの比較

説明
  • テキストを term に分割するために使用される転置インデックスを使用してクエリされた結果は、転置インデックスを使用せずにクエリされた結果とは異なります。転置インデックスは、列の値を term に分割し、 term を小文字に変換することで正規化します。したがって、転置インデックスを使用してクエリされた結果は、転置インデックスを使用せずにクエリされた結果よりも多くなります。

  • 一部の例では、データセットが小さいため、クエリのパフォーマンスに大きな違いはありません。データセットが大きいほど、パフォーマンスの差が大きくなります。

全文検索
  • comment 列に OLAP を含む行の数をカウントします。

    • LIKE 条件に基づいて、comment 列に OLAP を含む行の数をカウントします。クエリには 0.18 秒かかります。

      SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%';
      +---------+
      | count() |
      +---------+
      |      34 |
      +---------+
      1 row in set (0.18 sec)
    • 全文検索キーワード MATCH_ANY に基づいて、comment 列に OLAP を含む行の数をカウントします。クエリには 0.02 秒かかります。全文検索キーワードに基づくクエリのパフォーマンスは、LIKE 条件に基づくクエリのパフォーマンスの 8 倍です。

      SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLAP';
      +---------+
      | count() |
      +---------+
      |      35 |
      +---------+
      1 row in set (0.02 sec)
  • comment 列に OLTP を含む行の数をカウントします。

    • LIKE 条件に基づいて、comment 列に OLTP を含む行の数をカウントします。クエリには 0.07 秒かかります。

      SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLTP%';
      +---------+
      | count() |
      +---------+
      |      48 |
      +---------+
      1 row in set (0.07 sec)
    • 全文検索キーワード MATCH_ANY に基づいて、comment 列に OLTP を含む行の数をカウントします。クエリには 0.01 秒かかります。全文検索キーワードに基づくクエリのパフォーマンスは、LIKE 条件に基づくクエリのパフォーマンスの 6 倍です。

      SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLTP';
      +---------+
      | count() |
      +---------+
      |      51 |
      +---------+
      1 row in set (0.01 sec)
  • comment 列に OLAPOLTP の両方を含む行の数をカウントします。

    • LIKE 条件に基づいて、comment 列に OLAP と OLTP の両方を含む行の数をカウントします。クエリには 0.13 秒かかります。

      SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%' AND comment LIKE '%OLTP%';
      +---------+
      | count() |
      +---------+
      |      14 |
      +---------+
      1 row in set (0.13 sec)
    • 全文検索キーワード MATCH_ALL に基づいて、comment 列に OLAP と OLTP の両方を含む行の数をカウントします。クエリには 0.01 秒かかります。全文検索キーワードに基づくクエリのパフォーマンスは、LIKE 条件に基づくクエリのパフォーマンスの 12 倍です。

       SELECT count() FROM hackernews_1m WHERE comment MATCH_ALL 'OLAP OLTP';
      +---------+
      | count() |
      +---------+
      |      15 |
      +---------+
      1 row in set (0.01 sec)
  • comment 列に OLAP または OLTP を含む行の数をカウントします。

    • LIKE 条件に基づいて、comment 列に OLAP または OLTP を含む行の数をカウントします。クエリには 0.12 秒かかります。

      SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%' OR comment LIKE '%OLTP%';
      +---------+
      | count() |
      +---------+
      |      68 |
      +---------+
      1 row in set (0.12 sec)
    • 全文検索キーワードに基づいて、comment 列に OLAP または OLTP を含む行の数をカウントします。クエリには 0.01 秒かかります。全文検索キーワードに基づくクエリのパフォーマンスは、LIKE 条件に基づくクエリのパフォーマンスの 11 倍です。

      SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLAP OLTP';
      +---------+
      | count() |
      +---------+
      |      71 |
      +---------+
      1 row in set (0.01 sec)

等価クエリまたは範囲クエリ

  • DATETIME 型のデータに対する列範囲クエリのパフォーマンスを比較します。

    1. 転置インデックスが作成される前に、timestamp 列で値が 2007-08-23 04:17:00 より大きいデータをクエリします。クエリには 0.03 秒かかります。

       SELECT count() FROM hackernews_1m WHERE timestamp > '2007-08-23 04:17:00';
      +---------+
      | count() |
      +---------+
      |  999081 |
      +---------+
      1 row in set (0.03 sec)
    2. timestamp 列に転置インデックスを作成します。

      CREATE INDEX idx_timestamp ON hackernews_1m(timestamp) USING INVERTED;
      Query OK, 0 rows affected (0.03 sec)
    3. インデックスの作成進捗状況をクエリします。FinishTime パラメーターと CreateTime パラメーターの値の差に基づいて、100 万件のデータエントリを含む timestamp 列に転置インデックスを作成するのにわずか 1 秒しかかからないことがわかります。

      SHOW ALTER TABLE COLUMN;
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      | JobId | TableName     | CreateTime              | FinishTime              | IndexName     | IndexId | OriginIndexId | SchemaVersion | TransactionId | State    | Msg  | Progress | Timeout |
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      | 10030 | hackernews_1m | 2023-02-10 19:44:12.929 | 2023-02-10 19:44:13.938 | hackernews_1m | 10031   | 10008         | 1:1994690496  | 3             | FINISHED |      | NULL     | 2592000 |
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      1 row in set (0.00 sec)
    4. 転置インデックスが作成された後、同じクエリ文を実行して、timestamp 列で値が 2007-08-23 04:17:00 より大きいデータをクエリします。クエリには 0.01 秒かかります。クエリのパフォーマンスは、転置インデックスが作成される前よりも 0.02 秒速くなります。

      SELECT count() FROM hackernews_1m WHERE timestamp > '2007-08-23 04:17:00';
      +---------+
      | count() |
      +---------+
      |  999081 |
      +---------+
      1 row in set (0.01 sec)
  • NUMERIC 型のデータに対する等価クエリのパフォーマンスを比較します。

    1. 転置インデックスが作成される前に、parent 列で値が 11189 であるデータをクエリします。

      SELECT count() FROM hackernews_1m WHERE parent = 11189;
      +---------+
      | count() |
      +---------+
      |       2 |
      +---------+
      1 row in set (0.01 sec)
    2. parent 列に、テキストを分割するために使用されない転置インデックスを作成します。

      -- NUMERIC 型の列に転置インデックスを作成する場合、トークナイザーを指定する必要はありません。
      -- ALTER TABLE t ADD INDEX は、転置インデックスを作成するための 2 番目の構文です。
      ALTER TABLE hackernews_1m ADD INDEX idx_parent(parent) USING INVERTED;
      Query OK, 0 rows affected (0.01 sec)
    3. インデックスの作成進捗状況をクエリします。

      SHOW ALTER TABLE COLUMN;
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      | JobId | TableName     | CreateTime              | FinishTime              | IndexName     | IndexId | OriginIndexId | SchemaVersion | TransactionId | State    | Msg  | Progress | Timeout |
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      | 10030 | hackernews_1m | 2023-02-10 19:44:12.929 | 2023-02-10 19:44:13.938 | hackernews_1m | 10031   | 10008         | 1:1994690496  | 3             | FINISHED |      | NULL     | 2592000 |
      | 10053 | hackernews_1m | 2023-02-10 19:49:32.893 | 2023-02-10 19:49:33.982 | hackernews_1m | 10054   | 10008         | 1:378856428   | 4             | FINISHED |      | NULL     | 2592000 |
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
    4. 転置インデックスが作成された後、同じクエリ文を実行して、parent 列で値が 11189 であるデータをクエリします。

      SELECT count() FROM hackernews_1m WHERE parent = 11189;
      +---------+
      | count() |
      +---------+
      |       2 |
      +---------+
      1 row in set (0.01 sec)
  • STRING 型のデータに対する等価クエリのパフォーマンスを比較します。

    1. 転置インデックスが作成される前に、author 列で値が faster であるデータをクエリします。クエリには 0.03 秒かかります。

      SELECT count() FROM hackernews_1m WHERE author = 'faster';
      +---------+
      | count() |
      +---------+
      |      20 |
      +---------+
      1 row in set (0.03 sec)
    2. author 列に、テキストを分割するために使用されない転置インデックスを作成します。

      -- この例では、author 列に転置インデックスが作成されます。author 列の各値は term に分割されず、term と見なされます。
      ALTER TABLE hackernews_1m ADD INDEX idx_author(author) USING INVERTED;
      Query OK, 0 rows affected (0.01 sec)
    3. インデックスの作成進捗状況をクエリします。

      -- 100 万件のデータエントリを含む author 列に、増分モードで転置インデックスを作成するのにわずか 1.5 秒しかかかりません。
      SHOW ALTER TABLE COLUMN;
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      | JobId | TableName     | CreateTime              | FinishTime              | IndexName     | IndexId | OriginIndexId | SchemaVersion | TransactionId | State    | Msg  | Progress | Timeout |
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      | 10030 | hackernews_1m | 2023-02-10 19:44:12.929 | 2023-02-10 19:44:13.938 | hackernews_1m | 10031   | 10008         | 1:1994690496  | 3             | FINISHED |      | NULL     | 2592000 |
      | 10053 | hackernews_1m | 2023-02-10 19:49:32.893 | 2023-02-10 19:49:33.982 | hackernews_1m | 10054   | 10008         | 1:378856428   | 4             | FINISHED |      | NULL     | 2592000 |
      | 10076 | hackernews_1m | 2023-02-10 19:54:20.046 | 2023-02-10 19:54:21.521 | hackernews_1m | 10077   | 10008         | 1:1335127701  | 5             | FINISHED |      | NULL     | 2592000 |
      +-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
      
    4. 転置インデックスが作成された後、同じクエリ文を実行して、author 列で値が faster であるデータをクエリします。クエリには 0.01 秒かかります。クエリのパフォーマンスは、転置インデックスが作成される前よりも 0.02 秒速くなります。

      -- 転置インデックスが作成された後、文字列に対する等価クエリも大幅に高速化されます。
      SELECT count() FROM hackernews_1m WHERE author = 'faster';
      +---------+
      | count() |
      +---------+
      |      20 |
      +---------+
      1 row in set (0.01 sec)

TOKENIZE 関数

TOKENIZE 関数は、連続テキストを個別の term またはフレーズにトークン化できます。TOKENIZE 関数は、転置インデックスの作成と使用にとって重要であり、転置インデックスと密接に関連しています。トークン化の品質と方法は、転置インデックスの品質とパフォーマンスに直接影響します。

TOKENIZE 関数を呼び出して、連続テキストのトークン化結果をクエリすることもできます。TOKENIZE 関数には、parser パラメーターと parser_mode パラメーターが含まれています。次の表に、パラメーターを示します。

パラメーター

説明

parser

トークナイザー。デフォルトでは、このパラメーターは空のままです。これは、テキストがトークン化されないことを指定します。有効な値:

  • english: 英語のトークナイザー。英語の term を含むフィールドに適しています。このトークナイザーは、スペースと句読点を使用してテキストを term にトークン化し、高パフォーマンスを提供します。

  • chinese: 中国語のトークナイザー。中国語の term を含むフィールドに適しています。このトークナイザーは、英語のトークナイザーよりもパフォーマンスが低くなります。

  • unicode: 混合 Unicode トークナイザー。英語と中国語の term を含むフィールドに適しています。このトークナイザーは、電子メールアドレス、IP アドレス、および文字と数字の組み合わせのプレフィックスとサフィックスをトークン化できます。また、中国語の term を文字ごとにトークン化することもできます。

parser_mode

単語トークン化モード。単語トークン化の粒度は、単語トークン化モードによって異なります。

デフォルトでは、すべてのトークナイザーに coarse_grained モードが使用されます。coarse_grained モードでは、テキストは長い term にトークン化されます。たとえば、武汉市长江大桥 は、次の 2 つの term にトークン化されます: 武汉市长江大桥

parser=chinese 設定が構成されている場合、中国語のトークナイザーが使用され、fine_grained モードがサポートされます。fine_grained モードでは、テキストは短い term にトークン化されます。たとえば、武汉市长江大桥 は、次の 6 つの term にトークン化されます: 武汉武汉市市长长江长江大桥、および 大桥

-- 英語の単語トークン化結果
SELECT TOKENIZE('I love CHINA','"parser"="english"');
+------------------------------------------------+
| tokenize('I love CHINA', '"parser"="english"') |
+------------------------------------------------+
| ["i", "love", "china"]                         |
+------------------------------------------------+
1 row in set (0.02 sec)

-- 中国語のトークナイザーを使用して実装された、ファイングレイン単語トークン化結果。
SELECT TOKENIZE('武汉长江大桥','"parser"="chinese","parser_mode"="fine_grained"');
+-----------------------------------------------------------------------------------+
| tokenize('武汉长江大桥', '"parser"="chinese","parser_mode"="fine_grained"')       |
+-----------------------------------------------------------------------------------+
| ["武汉", "武汉长江大桥", "长江", "长江大桥", "大桥"]                              |
+-----------------------------------------------------------------------------------+
1 row in set (0.02 sec)

-- 中国語のトークナイザーを使用して実装された、コースグレイン単語トークン化結果。
SELECT TOKENIZE('武汉市长江大桥','"parser"="chinese","parser_mode"="coarse_grained"');
+----------------------------------------------------------------------------------------+
| tokenize('武汉市长江大桥', '"parser"="chinese","parser_mode"="coarse_grained"')        |
+----------------------------------------------------------------------------------------+
| ["武汉市", "长江大桥"]                                                                 |
+----------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

-- 多言語テキストの単語トークン化結果
SELECT TOKENIZE('I love CHINA 我爱我的祖国','"parser"="unicode"');
+-------------------------------------------------------------------+
| tokenize('I love CHINA 我爱我的祖国', '"parser"="unicode"')       |
+-------------------------------------------------------------------+
| ["i", "love", "china", "我", "爱", "我", "的", "祖", "国"]        |
+-------------------------------------------------------------------+
1 row in set (0.02 sec)