使用二级索引 (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)
因此,使用 2i 的难点之一就得到了说明。 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)