使用次要索引 (2i)
建立次要索引 (2i)
在定義表格後,在一個或多個欄位上建立索引。使用 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)
因此,說明了使用 2is 的其中一個困難點。 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)