CREATE INDEX
テーブルの単一列に対して、新しいセカンダリインデックス(2i)またはストレージアタッチインデックス(SAI)を定義します。
Apache Cassandraは、`PRIMARY KEY`のパーティション列およびクラスタ列、コレクション、および静的列を含む、ほとんどの列に対してセカンダリインデックスまたはストレージアタッチインデックスの作成をサポートしています。マップの場合、キー、値、またはエントリ(キー:値ペア)を使用してインデックスを作成できます。
次のものを除くすべての列データ型がSAIインデックスでサポートされています。
-
カウンター
-
フリーズされていないユーザー定義型(UDT)
参照: ストレージアタッチインデックス(SAI)についてはCREATE CUSTOM INDEX、DROP INDEX を参照してください。
構文
BNF定義
index_name::= re('[a-zA-Z_0-9]+')
CREATE INDEX [ IF NOT EXISTS ] <index_name> ON [<keyspace_name>.]<table_name> ( [ ( KEYS | FULL | ENTRIES ) ] <column_name>) // | [ (KEYS(<map_name>)) ] // | [ (VALUES(<map_name>)) ] // | [ (ENTRIES(<map_name>)) ] [USING 'sai'] [ WITH OPTIONS = { <option_map> } ];
構文規則 | 説明 |
---|---|
UPPERCASE |
リテラルキーワード。 |
Lowercase |
リテラルではない。 |
|
変数値。ユーザー定義の値に置き換えてください。 |
|
オプション。角かっこ(`[]`)で囲まれたコマンド引数はオプションです。角かっこは入力しないでください。 |
|
グループ。丸かっこ(`(` `)`)は、選択するグループを識別します。丸かっこは入力しないでください。 |
|
または。縦棒(`|`)は代替要素を分離します。いずれかの要素を入力します。縦棒は入力しないでください。 |
|
繰り返し可能。省略記号(`...`)は、必要なだけ構文要素を繰り返すことができることを示します。 |
|
単一引用符(`'`)は、CQLステートメント内のリテラル文字列を囲む必要があります。大文字を保持するには、単一引用符を使用します。 |
|
マップコレクション。中かっこ(`{ }`)は、マップコレクションまたはキーと値のペアを囲みます。コロンはキーと値を区切ります。 |
セット、リスト、マップ、またはタプル。山かっこ(`< >`)は、セット、リスト、マップ、またはタプル内のデータ型を囲みます。データ型をカンマで区切ります。 |
|
|
CQLステートメントを終了します。セミコロン(`;`)は、すべてのCQLステートメントを終了します。 |
|
コマンドラインオプションをコマンド引数から区切るには、2つのハイフン(`--`)を使用します。この構文は、引数がコマンドラインオプションと間違われる可能性がある場合に便利です。 |
|
検索CQLのみ:単一引用符(`'`)は、XMLスキーマ宣言全体を囲みます。 |
|
検索CQLのみ:スキーマファイルとsolrConfigファイル内のXML要素を上書きするエンティティとリテラル値を識別します。 |
必須パラメータ
パラメータ |
説明 |
table_name |
インデックスを作成するテーブルの名前。 |
column_name |
インデックスを作成する列の名前。SAIでは、名前に英数字とアンダースコアのみを使用できます。SAIは、他の文字を含む列名にインデックスを定義しようとすると、`InvalidRequestException`を返し、インデックスを作成しません。 |
オプションパラメータ
パラメータ |
説明 |
index_name |
インデックスの名前。特殊文字を使用したり、大文字を保持する場合は、引用符で囲んでください。名前が指定されていない場合、Apache Cassandraはインデックスに `<table_name>\_<column_name>\_idx` という名前を付けます。 |
keyspace_name |
インデックスを作成するテーブルを含むキースペースの名前。名前が指定されていない場合は、現在のキースペースが使用されます。 |
map_name |
コレクションで使用し、 `CREATE TABLE` … `map(<map_name>)`で指定された `map_name`の識別子。コレクションタイプ `list` および `set`には、通常の列構文が適用されます。 |
option_map |
JSONの単純な形式でオプションを定義します。 |
|
|
文字列値の照合で大文字と小文字を区別しません。デフォルト: `true` |
|
|
`true`に設定すると、インデックス付き文字列に対してUnicode正規化を実行します。SAIは、Normalization Form C (NFC) Unicodeをサポートしています。`true`に設定すると、SAIは特定のUnicode文字の異なるバージョンを単一のバージョンに正規化し、インデックス内のすべてのマークと記号を保持します。たとえば、SAIは文字 Å (U+212B)をÅ (U+00C5)に変更します。 実装が文字列を正規化された形式で保持する場合、同等の文字列には一意のバイナリ表現があります。Unicode Standard Annex #15, Unicode Normalization Formsを参照してください。 デフォルト: `false`。 |
|
|
`true`に設定すると、SAIは基本ラテンUnicodeブロック(最初の127のASCII文字)にないアルファベット、数字、および記号文字を、存在する場合はASCII相当に変換します。たとえば、このオプションはàをaに変更します。デフォルト: `false`。 |
|
|
ベクトル検索は、関連する一致を識別するためにベクトル間の類似性または距離の計算に依存します。類似性関数は、2つのベクトル間の類似性を計算するために使用されます。有効なオプションは、 `EUCLIDEAN`、 `DOT_PRODUCT`、 `COSINE`です。デフォルト: `COSINE` |
使用上の注意
列にすでにデータが含まれている場合、このステートメントの実行中にインデックスが作成されます。インデックスが作成された後、列のデータが変更されると自動的に更新されます。
`CREATE INDEX` コマンドを使用したインデックス作成は、パフォーマンスに影響を与える可能性があります。インデックスを作成する前に、いつ、インデックスを作成すべきでない場合を理解しておいてください。
制限: カウンタ列のインデックス作成はサポートされていません。
SAIインデックス
テーブルの複合パーティションキー、つまり複数の列で構成されるパーティションキー内のいずれかの列にSAIインデックスを定義できます。これらの列のいずれかに基づいてクエリを実行する必要がある場合、SAIインデックスは役立つオプションです。実際、必要に応じて、複合パーティションキー内の各列にSAIインデックスを定義できます。
データベーステーブルの任意の列に基づいて1つ以上のSAIインデックスを定義すると、クエリでインデックス付きの列を使用して結果をフィルタリングできます。
SAIクエリオペレーター
SAIは、SAIインデックスを持つテーブルに対して次のクエリオペレーターをサポートしています。
-
数値: `=`, `<`, `>`, `<=`, `>=`, `AND`, `OR`, `IN`
-
文字列: `=`, `CONTAINS`, `CONTAINS KEY`, `AND`, `OR`, `IN`
SAIは、SAIインデックスを持つテーブルに対して次のクエリオペレーターをサポートしていません。
-
文字列または数値: `LIKE`
SAIセクションを参照してください。
例
クラスタリング列にSAIインデックスを作成する
複合パーティションキーを持つテーブルを定義し、クラスタリング列にインデックスを作成します。
CREATE TABLE IF NOT EXISTS cycling.rank_by_year_and_name (
race_year int,
race_name text,
cyclist_name text,
rank int,
PRIMARY KEY ((race_year, race_name), rank)
);
CREATE INDEX IF NOT EXISTS rank_idx
ON cycling.rank_by_year_and_name (rank);
SELECT * FROM rank_by_year_and_name WHERE rank = 1;
race_year | race_name | rank | cyclist_name
-----------+--------------------------------------------+------+-------------------
2014 | 4th Tour of Beijing | 1 | Phillippe GILBERT
2014 | Tour of Japan - Stage 4 - Minami > Shinshu | 1 | Daniel MARTIN
2015 | Giro d'Italia - Stage 11 - Forli > Imola | 1 | Ilnur ZAKARIN
2015 | Tour of Japan - Stage 4 - Minami > Shinshu | 1 | Benjamin PRADES
(4 rows)
set または list コレクションに対するインデックスの作成
他の列に対する場合と同様に、set または list コレクション列にインデックスを作成します。CREATE INDEX
ステートメントの最後に、コレクション列の名前を括弧で囲みます。たとえば、チームのコレクションを cyclist_career_teams
テーブルに追加して、teams set のデータにインデックスを付けます。
CREATE TABLE IF NOT EXISTS cycling.cyclist_career_teams (
id UUID PRIMARY KEY,
lastname text,
teams set<text>
);
CREATE INDEX IF NOT EXISTS teams_idx
ON cycling.cyclist_career_teams (teams);
SELECT * FROM cyclist_career_teams WHERE teams CONTAINS 'Rabobank-Liv Woman Cycling Team';
id | lastname | teams
--------------------------------------+-----------------+------------------------------------------------------------------------------------------------------
5b6962dd-3f90-4c93-8f61-eabfa4a803e2 | VOS | {'Nederland bloeit', 'Rabobank Women Team', 'Rabobank-Liv Giant', 'Rabobank-Liv Woman Cycling Team'}
1c9ebc13-1eab-4ad5-be87-dce433216d40 | BRAND | {'AA Drink - Leontien.nl', 'Leontien.nl', 'Rabobank-Liv Giant', 'Rabobank-Liv Woman Cycling Team'}
e7cd5752-bc0d-4157-a80f-7523add8dbcd | VAN DER BREGGEN | {'Rabobank-Liv Woman Cycling Team', 'Sengers Ladies Cycling Team', 'Team Flexpoint'}
(3 rows)
マップキーに対するインデックスの作成
マップコレクションキーにインデックスを作成できます。コレクションのマップ値のインデックスが存在する場合は、マップコレクションキーのインデックスを作成する前に、そのインデックスを削除してください。サイクリストテーブルに、nation
がマップキーで、`Canada` がマップ値であるようなマップデータが含まれていると仮定します。
{'nation':'CANADA' }
マップキーにインデックスを付けるには、CREATE INDEX ステートメントで、ネストされた括弧の中に KEYS
キーワードとマップ名を使用します。テーブルに対して SELECT
クエリを実行するには、WHERE
句でCONTAINS KEYを使用します。このクエリは、2015 年のエントリを持つサイクリストチームを返します。
CREATE TABLE IF NOT EXISTS cycling.cyclist_teams (
id uuid PRIMARY KEY,
firstname text,
lastname text,
teams map<int, text>
);
CREATE INDEX IF NOT EXISTS team_year_keys_idx
ON cycling.cyclist_teams ( KEYS (teams) );
SELECT *
FROM cycling.cyclist_teams
WHERE teams CONTAINS KEY 2015;
id | firstname | lastname | teams
--------------------------------------+-----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
cb07baad-eac8-4f65-b28a-bddc06a0de23 | Elizabeth | ARMITSTEAD | {2011: 'Team Garmin - Cervelo', 2012: 'AA Drink - Leontien.nl', 2013: 'Boels:Dolmans Cycling Team', 2014: 'Boels:Dolmans Cycling Team', 2015: 'Boels:Dolmans Cycling Team'}
5b6962dd-3f90-4c93-8f61-eabfa4a803e2 | Marianne | VOS | {2015: 'Rabobank-Liv Woman Cycling Team'}
(2 rows)
マップエントリに対するインデックスの作成
マップエントリにインデックスを作成できます。ENTRIES
インデックスは、既存のインデックスを持たないテーブルのマップ列にのみ作成できます。
コレクションエントリにインデックスを付けるには、ネストされた括弧の中に ENTRIES
キーワードとマップ名を使用します。テーブル内のマップエントリをクエリするには、マップ名と値を含む WHERE
句を使用します。このクエリは、同じ年齢のサイクリストを検索します。
CREATE TABLE IF NOT EXISTS cycling.birthday_list (
cyclist_name text PRIMARY KEY,
blist map<text, text>
);
CREATE INDEX IF NOT EXISTS blist_idx
ON cycling.birthday_list ( ENTRIES(blist) );
SELECT *
FROM cycling.birthday_list
WHERE blist[ 'age' ] = '23';
cyclist_name | blist
------------------+----------------------------------------------------------
Claudio HEINEN | {'age': '23', 'bday': '27/07/1992', 'nation': 'GERMANY'}
Laurence BOURQUE | {'age': '23', 'bday': '27/07/1992', 'nation': 'CANADA'}
(2 rows)
同じインデックスを使用して、同じ国のサイクリストを検索します
CREATE TABLE IF NOT EXISTS cycling.birthday_list (
cyclist_name text PRIMARY KEY,
blist map<text, text>
);
CREATE INDEX IF NOT EXISTS blist_idx
ON cycling.birthday_list ( ENTRIES(blist) );
SELECT *
FROM cycling.birthday_list
WHERE blist[ 'nation' ] = 'NETHERLANDS';
cyclist_name | blist
---------------+--------------------------------------------------------------
Luc HAGENAARS | {'age': '28', 'bday': '27/07/1987', 'nation': 'NETHERLANDS'}
Toine POELS | {'age': '52', 'bday': '27/07/1963', 'nation': 'NETHERLANDS'}
(2 rows)
マップ値に対するインデックスの作成
マップ値にインデックスを作成するには、ネストされた括弧の中に VALUES
キーワードとマップ名を使用します。テーブルをクエリするには、マップ名とその中に含まれる値を含む WHERE
句を使用します。
CREATE TABLE IF NOT EXISTS cycling.birthday_list (
cyclist_name text PRIMARY KEY,
blist map<text, text>
);
CREATE INDEX IF NOT EXISTS blist_values_idx
ON cycling.birthday_list ( VALUES(blist) );
SELECT *
FROM cycling.birthday_list
WHERE blist CONTAINS 'NETHERLANDS';
cyclist_name | blist
---------------+--------------------------------------------------------------
Luc HAGENAARS | {'age': '28', 'bday': '27/07/1987', 'nation': 'NETHERLANDS'}
Toine POELS | {'age': '52', 'bday': '27/07/1963', 'nation': 'NETHERLANDS'}
(2 rows)
frozen コレクションの完全なコンテンツに対するインデックスの作成
完全な FROZEN
コレクションにインデックスを作成できます。FULL
インデックスは、既存のインデックスを持たないテーブルの set、list、または map 列に作成できます。
FROZEN
list
の完全なコンテンツにインデックスを作成します。この例のテーブルは、サイクリストが参加したプロ勝利数、グランドツアーレース、クラシックレースの数を格納します。コレクションエントリにインデックスを付けるには、ネストされた括弧の中に FULL
キーワードとコレクション名を使用します。たとえば、frozen list rnumbers
にインデックスを付けます。テーブルをクエリするには、コレクション名と値を含む WHERE
句を使用します。
CREATE TABLE IF NOT EXISTS cycling.race_starts (
cyclist_name text PRIMARY KEY,
rnumbers FROZEN<LIST<int>>
);
CREATE INDEX IF NOT EXISTS rnumbers_idx
ON cycling.race_starts ( FULL(rnumbers) );
SELECT *
FROM cycling.race_starts
WHERE rnumbers = [39, 7, 14];
cyclist_name | rnumbers
----------------+-------------
John DEGENKOLB | [39, 7, 14]
(1 rows)