セカンダリインデックス(2i)の操作
セカンダリインデックス(2i)の作成
テーブルを定義した後、1つ以上の列にインデックスを作成します。2iで作成されたセカンダリインデックスは、テーブルのパーティションキー以外の列を使用してテーブルをクエリするために使用できます。
本番環境では、特定の列はカーディナリティによっては適切な選択ではない場合があります。
同じテーブルにストレージアタッチインデックス(SAI)を追加しないでください。これらのインデックスタイプの違いについては、概要を参照してください。 |
シンプルな2iの作成
テーブルにシンプルな2iインデックスを作成して、インデックスの動作を確認します。まず、サイクリストに関する統計を生成するテーブルcycling.alt_stats
を作成します
CREATE TABLE IF NOT EXISTS cycling.cyclist_alt_stats (
id UUID PRIMARY KEY,
lastname text,
birthday date,
nationality text,
weight float,
w_units text,
height float,
first_race date,
last_race date
);
次に、birthday
とnationality
の列にインデックスを作成します。
CREATE INDEX IF NOT EXISTS birthday_idx
ON cycling.cyclist_alt_stats (birthday);
CREATE INDEX IF NOT EXISTS nationality_idx
ON cycling.cyclist_alt_stats (nationality);
次のクエリは、指定されたbirthday
とnationality
を持つサイクリストを取得しようとします。クエリはエラーを返します。
SELECT *
FROM cycling.cyclist_alt_stats
WHERE birthday = '1982-01-29'
AND nationality = 'Russia';
InvalidRequest: Error from server: code=2200 [Invalid query]
message="Cannot execute this query as it might involve data
filtering and thus may have unpredictable performance.
If you want to execute this query despite the performance
unpredictability, use ALLOW FILTERING"
インデックスは適切な低カーディナリティ列に作成されていますが、前のクエリはまだ失敗します。なぜでしょうか?
その答えは、定義されていないパーティションキーにあります。行の範囲を検索するなど、コストのかかる可能性のあるクエリを試みると、データベースはALLOW FILTERING
ディレクティブを必要とします。エラーは複数のインデックスが原因ではなく、クエリにパーティションキーの定義がないためです。
SELECT *
FROM cycling.cyclist_alt_stats
WHERE birthday = '1982-01-29'
AND nationality = 'Russia'
ALLOW FILTERING;
id | birthday | first_race | height | last_race | lastname | nationality | w_units | weight
--------------------------------------+------------+------------+--------+------------+----------+-------------+---------+--------
e0953617-07eb-4c82-8f91-3b2757981625 | 1982-01-29 | 1998-02-15 | 1.78 | 2017-04-16 | BRUTT | Russia | kg | 68
(1 rows)
したがって、2iを使用することの難しさの1つが示されました。SAIはほぼ常に良い選択肢です。
コレクション列に2iを作成する
コレクションをインデックス化してクエリし、特定の値を含むコレクションを見つけることができます。セットとリストは、マップのキーと値の性質を考慮して、マップとは少し異なる方法でインデックス化されます。
セットとリストは、コレクション列をインデックス化することによって見つかったすべての値をインデックス化できます。マップは、以下に示すメソッドを使用して、マップキー、マップ値、またはマップエントリをインデックス化できます。テーブル内の同じマップ列に複数のインデックスを作成して、マップキー、値、またはエントリをクエリできます。さらに、フリーズされたコレクションは、フリーズされたコレクションの完全なコンテンツをインデックス化するためにFULL
を使用してインデックス化できます。
セカンダリインデックスの使用に関するすべての注意点は、コレクションのインデックス化にも適用されます。 |
-
セットおよびリストコレクションの場合、列名にインデックスを作成します。特定のチームに所属したすべてのサイクリストを見つけるために、セットにインデックスを作成します。
CREATE INDEX IF NOT EXISTS teams_idx
ON cycling.cyclist_career_teams (teams);
SELECT *
FROM cycling.cyclist_career_teams
WHERE teams CONTAINS 'Rabobank-Liv Giant';
id | lastname | teams
--------------------------------------+----------+-----------------------------------------------------------------------------
-----------------------
1c9ebc13-1eab-4ad5-be87-dce433216d40 | BRAND | {'AA Drink - Leontien.nl', 'Leontien.nl', 'Rabobank-Liv Giant', 'Rabobank-Li
v Woman Cycling Team'}
(1 rows)
-
マップコレクションの場合、マップキー、マップ値、またはマップエントリにインデックスを作成します。特定の年のすべてのサイクリスト/チームの組み合わせを見つけるために、マップキーにインデックスを作成します。
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
を使用するインデックスは、マップに対してのみ有効です。
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)
-
同じインデックスを使用して、同じ国のサイクリストを見つけます。
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)
-
マップ値にインデックスを作成し、指定されたマップにある特定の値を持つサイクリストを見つけます。
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
マップの全コンテンツにインデックスを作成します。この例のテーブルは、サイクリストが参加したプロレース、グランドツアーレース、およびクラシックレースの数を格納します。SELECTステートメントは、プロレースでの勝利数39、グランドツアースタート7、クラシックスタート14のサイクリストを見つけます。
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)
セカンダリインデックス(2i)の変更
セカンダリインデックスは変更できません。2iを変更する場合は、インデックスを削除し、新しいインデックスを作成する必要があります。