Apache Cassandra 中的自定义索引(SAI)创建指南
存储附加索引(SAI)概述
存储附加索引(Storage-Attached Indexing, SAI)是Apache Cassandra中一种高效的二级索引实现方式。与传统二级索引相比,SAI提供了更好的查询性能和更低的资源消耗。它直接在存储层实现索引功能,避免了传统二级索引的一些性能瓶颈。
SAI索引支持的数据类型
SAI支持绝大多数Cassandra数据类型,但有以下例外情况:
- 计数器(counter)类型
- 非冻结的用户定义类型(non-frozen UDT)
重要限制:不能为单列分区键创建SAI索引。如果尝试这样做,系统会返回错误。但对于复合分区键(由多列组成的分区键),可以为其中的单个列创建SAI索引。
SAI索引创建语法
创建SAI索引的基本语法如下:
CREATE CUSTOM INDEX [ IF NOT EXISTS ] [ 索引名称 ]
ON [ 键空间名称.]表名称 (列名称)
| [ (KEYS(映射名称)) ]
| [ (VALUES(映射名称)) ]
| [ (ENTRIES(映射名称)) ]
USING 'StorageAttachedIndex'
[ WITH OPTIONS = { 选项映射 } ];
语法元素说明
- 索引名称:可选参数,如果不指定,默认格式为
<表名>_<列名>_idx
- 列名称:要创建索引的表列名,只允许字母数字和下划线
- 映射名称:用于集合类型(map)的索引,可以索引键、值或条目
- 选项映射:JSON格式的索引选项配置
SAI索引选项
SAI提供了几个有用的索引选项:
| 选项名称 | 描述 | 默认值 | |---------|------|-------| | case_sensitive
| 字符串匹配是否区分大小写 | true | | normalize
| 是否对索引字符串执行Unicode标准化(NFC形式) | false | | ascii
| 是否将非基本拉丁字符转换为其ASCII等效字符 | false | | similarity_function
| 向量搜索使用的相似度计算函数(支持EUCLIDEAN, DOT_PRODUCT, COSINE) | COSINE |
SAI支持的查询操作符
SAI支持以下查询操作符:
- 等于(=)
- 不等于(!=)
- 大于(>)
- 大于等于(>=)
- 小于(<)
- 小于等于(<=)
- IN
- CONTAINS (用于集合)
- CONTAINS KEY (用于map)
不支持的操作符包括:
- LIKE
- IS NOT NULL
- 其他复杂表达式
实际应用示例
基本索引创建
假设我们有一个cycling.cyclist_semi_pro
表,可以为其创建多个SAI索引:
CREATE CUSTOM INDEX ON cycling.cyclist_semi_pro (age) USING 'StorageAttachedIndex';
CREATE CUSTOM INDEX ON cycling.cyclist_semi_pro (firstname) USING 'StorageAttachedIndex';
集合类型索引示例
Map类型索引
- 创建表和索引:
CREATE TABLE audit (id int PRIMARY KEY, text_map map<text, text>);
-- 为map的键、值和条目分别创建索引
CREATE CUSTOM INDEX ON audit (KEYS(text_map)) USING 'StorageAttachedIndex';
CREATE CUSTOM INDEX ON audit (VALUES(text_map)) USING 'StorageAttachedIndex';
CREATE CUSTOM INDEX ON audit (ENTRIES(text_map)) USING 'StorageAttachedIndex';
- 查询示例:
-- 查询特定键值对
SELECT * FROM audit WHERE text_map['Irene'] = 'Cantona';
-- 查询包含特定键的记录
SELECT * FROM audit WHERE text_map CONTAINS KEY 'Giovani';
-- 查询包含特定值的记录
SELECT * FROM audit WHERE text_map CONTAINS 'Silva';
List和Set类型索引
- List类型示例:
CREATE TABLE calendar (key int PRIMARY KEY, years list<int>);
CREATE CUSTOM INDEX ON calendar(years) USING 'StorageAttachedIndex';
-- 插入数据
INSERT INTO calendar (key, years) VALUES (0, [1990,1996]);
-- 查询包含特定元素的记录
SELECT * FROM calendar WHERE years CONTAINS 1990;
- Set类型示例:
CREATE TABLE calendar2 (key int PRIMARY KEY, years set<int>);
CREATE CUSTOM INDEX ON calendar2(years) USING 'StorageAttachedIndex';
-- 插入数据
INSERT INTO calendar2 (key, years) VALUES (0, {1990,1996});
-- 查询包含特定元素的记录
SELECT * FROM calendar2 WHERE years CONTAINS 1990;
最佳实践建议
- 对于频繁查询的非主键列,考虑创建SAI索引
- 对于复合分区键中的列,如果需要单独查询,SAI索引是很好的选择
- 对于集合类型(Map/List/Set)的查询,SAI提供了高效的CONTAINS操作支持
- 考虑使用索引选项优化特定场景,如不区分大小写的搜索或Unicode标准化
通过合理使用SAI索引,可以显著提升Apache Cassandra的查询性能,特别是在需要基于非主键列或集合元素进行过滤的场景下。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考