1. 首页 > Cassandra教程 > 正文

Cassandra教程FG008-Cassandra索引与查询优化实战

本文档风哥主要介绍Cassandra数据库索引与查询优化实战,包括索引概述、索引类型、查询优化概念、索引设计原则、索引创建策略、查询优化策略、SAI索引实战、SASI索引实战、查询优化实战、用户查询优化实战、订单查询优化实战、日志查询优化实战等内容,风哥教程参考Cassandra官方文档Indexing和Performance内容编写,适合DBA人员和开发人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。

Part01-基础概念与理论知识

1.1 Cassandra数据库索引概述

Cassandra数据库索引是提高查询效率的重要手段。与传统关系型数据库不同,Cassandra的索引机制有其独特的特点和限制。更多视频教程www.fgedu.net.cn

1.1.1 Cassandra数据库索引特点

# Cassandra索引特点

# 1. 索引类型
– 二级索引(Secondary Index)
– SAI索引(Storage-Attached Index)
– SASI索引(SSTable Attached Secondary Index)
– 全文搜索索引

# 2. 索引作用
– 支持非分区键列查询
– 提高查询效率
– 避免全表扫描

# 3. 索引限制
– 高基数列索引效率低
– 索引增加写入开销
– 索引占用存储空间
– 索引维护成本

# 4. 索引适用场景
– 低到中等基数列
– 查询频率高的列
– 等值查询场景
– 范围查询场景(SAI)

# 索引与分区键关系
分区键查询: 直接定位分区,效率最高
索引查询: 先查索引表,再查数据表,效率较低

# 查询优先级
1. 分区键查询(最优)
2. 分区键+聚簇键查询
3. 分区键+索引查询
4. 索引查询
5. ALLOW FILTERING(最差)

1.1.2 Cassandra数据库索引工作原理

# 索引工作原理

# 二级索引工作原理
1. 创建索引时,Cassandra创建隐藏的索引表
2. 索引表存储索引列值到分区键的映射
3. 查询时,先查索引表获取分区键
4. 再根据分区键查询数据表

# 索引表结构
索引列值 → 分区键列表

# 示例
原表: fgedu_users (user_id PRIMARY KEY, email, name)
索引: CREATE INDEX idx_email ON fgedu_users (email);

索引表结构:
email | user_id
—————-+————————————–
user1@fgedu.cn | uuid-1
user2@fgedu.cn | uuid-2

# 查询过程
SELECT * FROM fgedu_users WHERE email = ‘user1@fgedu.cn’;
1. 查索引表: email = ‘user1@fgedu.cn’ → user_id = uuid-1
2. 查数据表: user_id = uuid-1 → 完整数据

# SAI索引工作原理
1. 索引数据存储在SSTable中
2. 支持范围查询和排序
3. 更高效的存储和查询

1.2 Cassandra数据库索引类型

Cassandra数据库索引类型详解:

1.2.1 Cassandra数据库二级索引

# 二级索引(Secondary Index)

# 特点
– Cassandra内置索引
– 创建隐藏索引表
– 支持等值查询
– 适用于低基数列

# 语法
CREATE INDEX [IF NOT EXISTS] index_name
ON table_name (column_name);

# 示例
CREATE INDEX idx_email ON fgedu_users (email);
CREATE INDEX idx_status ON fgedu_orders (status);

# 优点
– 创建简单
– 自动维护
– 支持等值查询

# 缺点
– 高基数列效率低
– 增加写入延迟
– 占用存储空间
– 不支持范围查询

# 适用场景
– 低基数列(如status、type)
– 查询频率高
– 等值查询

# 不适用场景
– 高基数列(如email、user_id)
– 范围查询
– 频繁更新的列

1.2.2 Cassandra数据库SAI索引

# SAI索引(Storage-Attached Index)

# 特点
– Cassandra 4.0引入
– 索引数据存储在SSTable中
– 支持范围查询
– 支持排序
– 更高效的存储

# 语法
CREATE CUSTOM INDEX index_name
ON table_name (column_name)
USING ‘StorageAttachedIndex’;

# 示例
CREATE CUSTOM INDEX idx_email_sai ON fgedu_users (email)
USING ‘StorageAttachedIndex’;

CREATE CUSTOM INDEX idx_created_sai ON fgedu_orders (created_at)
USING ‘StorageAttachedIndex’;

# 优点
– 支持范围查询
– 支持排序
– 存储效率高
– 查询性能好
– 支持多列索引

# 缺点
– 需要Cassandra 4.0+
– 增加写入开销
– 占用存储空间

# 适用场景
– 范围查询
– 排序查询
– 中等基数列
– 需要高性能查询

# SAI索引类型
1. SAI普通索引
– 支持等值和范围查询

2. SAI全文索引
– 支持文本搜索
– 支持模糊匹配

1.2.3 Cassandra数据库SASI索引

# SASI索引(SSTable Attached Secondary Index)

# 特点
– Cassandra 3.4引入
– 索引数据存储在SSTable中
– 支持范围查询
– 支持LIKE查询

# 语法
CREATE CUSTOM INDEX index_name
ON table_name (column_name)
USING ‘org.apache.cassandra.index.sasi.SASIIndex’
WITH OPTIONS = {
‘mode’: ‘MODE’,
‘analyzer_class’: ‘CLASS’,
‘case_sensitive’: ‘true|false’
};

# 示例
CREATE CUSTOM INDEX idx_name_sasi ON fgedu_users (user_name)
USING ‘org.apache.cassandra.index.sasi.SASIIndex’
WITH OPTIONS = {
‘mode’: ‘CONTAINS’,
‘analyzer_class’: ‘org.apache.cassandra.index.sasi.analyzer.StandardAnalyzer’,
‘case_sensitive’: ‘false’
};

# SASI模式
1. PREFIX: 前缀匹配
WHERE user_name LIKE ‘张%’

2. CONTAINS: 包含匹配
WHERE user_name LIKE ‘%张%’

3. SPARSE: 稀疏索引
适用于高基数列

# 优点
– 支持LIKE查询
– 支持范围查询
– 查询性能好

# 缺点
– 配置复杂
– 增加写入开销
– 维护成本高

# 适用场景
– 文本搜索
– LIKE查询
– 范围查询

1.3 Cassandra数据库查询优化概念

Cassandra数据库查询优化概念详解:

1.3.1 Cassandra数据库查询执行过程

# 查询执行过程

# 1. 查询解析
– 解析CQL语句
– 验证语法正确性
– 生成查询计划

# 2. 查询优化
– 确定分区键
– 选择索引
– 优化查询路径

# 3. 查询执行
– 定位分区
– 读取数据
– 过滤结果

# 4. 结果返回
– 组装结果集
– 返回客户端

# 查询类型
1. 分区键查询
– 直接定位分区
– 效率最高

2. 索引查询
– 先查索引表
– 再查数据表
– 效率中等

3. 全表扫描
– 扫描所有分区
– 效率最低
– 需要ALLOW FILTERING

# 查询优化目标
1. 减少扫描分区数
2. 减少扫描行数
3. 减少网络传输
4. 提高查询响应速度

1.3.2 Cassandra数据库查询性能影响因素

# 查询性能影响因素

# 1. 分区键设计
– 分区键选择影响数据分布
– 热点分区导致性能下降
– 分区大小影响查询效率

# 2. 索引设计
– 索引类型影响查询效率
– 索引列基数影响性能
– 索引维护影响写入性能

# 3. 数据量
– 数据量影响扫描时间
– 大分区影响查询效率
– 墓碑影响读取性能

# 4. 集群状态
– 节点数量影响并行度
– 网络延迟影响响应时间
– 节点负载影响性能

# 5. 一致性级别
– 一致性级别影响延迟
– 高一致性级别增加延迟
– 低一致性级别提高性能

# 6. 缓存配置
– 缓存命中率影响性能
– 缓存大小影响效果
– 缓存策略影响效率

# 性能优化方向
1. 优化分区键设计
2. 合理使用索引
3. 控制分区大小
4. 优化一致性级别
5. 配置合理缓存
6. 监控集群状态

Part02-生产环境规划与建议

2.1 Cassandra数据库索引设计原则

Cassandra数据库索引设计原则详解:

2.1.1 Cassandra数据库索引选择原则

# 索引选择原则

# 1. 优先考虑表结构设计
– 索引是补充手段
– 优先优化表结构
– 查询驱动设计

# 2. 评估列基数
– 低基数列: 二级索引
– 中等基数列: SAI索引
– 高基数列: 重新设计表结构

# 3. 评估查询模式
– 等值查询: 二级索引、SAI索引
– 范围查询: SAI索引
– 文本搜索: SASI索引、SAI全文索引

# 4. 评估更新频率
– 频繁更新: 谨慎使用索引
– 较少更新: 可使用索引
– 只读数据: 大量使用索引

# 5. 评估数据量
– 小数据量: 索引效果好
– 大数据量: 需要分区优化

# 索引决策流程
1. 分析查询需求
2. 评估是否需要索引
3. 选择索引类型
4. 创建索引
5. 测试性能
6. 调整优化

# 不建议使用索引的场景
1. 高基数列
2. 频繁更新的列
3. 写入密集型场景
4. 可以通过表结构优化解决

2.1.2 Cassandra数据库索引设计最佳实践

# 索引设计最佳实践

# 1. 索引数量控制
– 单表索引不超过3个
– 索引过多影响写入性能
– 选择最常用的查询列

# 2. 索引列选择
– 选择查询频率高的列
– 选择基数适中的列
– 选择更新频率低的列

# 3. 索引类型选择
– Cassandra 4.0+: 优先使用SAI
– Cassandra 3.x: 使用二级索引或SASI
– 文本搜索: 使用SASI或SAI全文索引

# 4. 索引命名规范
– 前缀idx_表示索引
– 包含表名和列名
– 示例: idx_users_email

# 5. 索引监控
– 监控索引大小
– 监控索引查询性能
– 监控索引维护开销

# 6. 索引维护
– 定期重建索引
– 清理无效索引
– 优化索引配置

# 索引设计检查清单
[ ] 查询需求已分析
[ ] 列基数已评估
[ ] 索引类型已选择
[ ] 索引命名规范
[ ] 性能测试已完成
[ ] 监控方案已制定

2.2 Cassandra数据库索引创建策略

Cassandra数据库索引创建策略详解:

2.2.1 Cassandra数据库索引创建时机

# 索引创建时机

# 1. 表创建后创建索引
– 先创建表
– 导入数据
– 创建索引

# 2. 数据量小时创建
– 数据量小时创建索引快
– 大数据量创建索引慢

# 3. 业务低峰期创建
– 索引创建消耗资源
– 避免高峰期创建

# 4. 索引创建步骤
步骤1: 分析查询需求
步骤2: 选择索引列
步骤3: 选择索引类型
步骤4: 创建索引
步骤5: 验证索引效果
步骤6: 监控索引性能

# 索引创建注意事项
1. 大表创建索引可能很慢
2. 创建索引期间性能下降
3. 建议在测试环境先验证
4. 监控创建进度

2.2.2 Cassandra数据库索引创建语法

# 索引创建语法

# 1. 二级索引
CREATE INDEX [IF NOT EXISTS] index_name
ON table_name (column_name);

# 示例
CREATE INDEX idx_email ON fgedu_users (email);
CREATE INDEX IF NOT EXISTS idx_status ON fgedu_orders (status);

# 2. SAI索引
CREATE CUSTOM INDEX index_name
ON table_name (column_name)
USING ‘StorageAttachedIndex’;

# 示例
CREATE CUSTOM INDEX idx_email_sai ON fgedu_users (email)
USING ‘StorageAttachedIndex’;

# 3. SASI索引
CREATE CUSTOM INDEX index_name
ON table_name (column_name)
USING ‘org.apache.cassandra.index.sasi.SASIIndex’
WITH OPTIONS = {
‘mode’: ‘MODE’,
‘analyzer_class’: ‘CLASS’
};

# 示例
CREATE CUSTOM INDEX idx_name_sasi ON fgedu_users (user_name)
USING ‘org.apache.cassandra.index.sasi.SASIIndex’
WITH OPTIONS = {‘mode’: ‘CONTAINS’};

# 4. 集合索引
CREATE INDEX idx_tags ON fgedu_users (tags); — SET
CREATE INDEX idx_attrs ON fgedu_users (KEYS(attributes)); — MAP keys
CREATE INDEX idx_attr_values ON fgedu_users (VALUES(attributes)); — MAP values
CREATE INDEX idx_attr_entries ON fgedu_users (ENTRIES(attributes)); — MAP entries

# 5. 删除索引
DROP INDEX [IF EXISTS] index_name;

# 示例
DROP INDEX IF EXISTS idx_email;

2.3 Cassandra数据库查询优化策略

Cassandra数据库查询优化策略详解:

2.3.1 Cassandra数据库查询优化方法

# 查询优化方法

# 1. 分区键优化
– 查询必须包含分区键
– 避免全表扫描
– 合理设计分区键

# 2. 聚簇键优化
– 利用聚簇键排序
– 支持范围查询
– 减少扫描行数

# 3. 索引优化
– 合理使用索引
– 选择合适的索引类型
– 监控索引性能

# 4. 分页优化
– 使用LIMIT分页
– 使用分页状态
– 避免大结果集

# 5. 一致性级别优化
– 选择合适的一致性级别
– 平衡一致性和性能
– 使用本地一致性

# 6. 并行查询优化
– 使用异步查询
– 并行查询多个分区
– 提高吞吐量

# 查询优化检查清单
[ ] 查询包含分区键
[ ] 使用聚簇键排序
[ ] 索引使用合理
[ ] 分页查询实现
[ ] 一致性级别合适
[ ] 并行查询优化

2.3.2 Cassandra数据库查询优化技巧

# 查询优化技巧

# 1. 避免SELECT *
# 不好的做法
SELECT * FROM fgedu_users WHERE user_id = ?;

# 好的做法
SELECT user_id, user_name, email FROM fgedu_users WHERE user_id = ?;

# 2. 使用LIMIT
SELECT * FROM fgedu_orders WHERE user_id = ? LIMIT 100;

# 3. 使用分页状态
# 应用代码实现
Statement statement = QueryBuilder.select()
.from(“fgedu_users”)
.where(eq(“user_id”, userId))
.setFetchSize(100);

ResultSet results = session.execute(statement);
PagingState pagingState = results.getExecutionInfo().getPagingState();

# 4. 使用IN查询(谨慎使用)
SELECT * FROM fgedu_users WHERE user_id IN (?, ?, ?);

# 5. 使用TOKEN查询(特殊情况)
SELECT * FROM fgedu_users WHERE TOKEN(user_id) > ? LIMIT 100;

# 6. 避免ALLOW FILTERING
# 不好的做法
SELECT * FROM fgedu_users WHERE age > 25 ALLOW FILTERING;

# 好的做法:创建索引或重新设计表结构

# 7. 使用并行查询
# 同时查询多个分区
List futures = new ArrayList<>();
for (UUID userId : userIds) {
futures.add(session.executeAsync(
“SELECT * FROM fgedu_users WHERE user_id = ?”, userId
));
}

风哥提示:查询优化是提高Cassandra性能的关键。优先优化表结构和分区键设计,合理使用索引,避免全表扫描。监控查询性能,及时发现和解决问题。学习交流加群风哥微信: itpux-com

Part03-生产环境项目实施方案

3.1 Cassandra数据库SAI索引实战

Cassandra数据库SAI索引实战:

3.1.1 Cassandra数据库创建SAI索引

# 连接Cassandra
# cqlsh 192.168.1.101 9042 -u fgedu -p Fgedu@2024
Connected to fgedu_cluster at 192.168.1.101:9042

# 切换到Keyspace
cqlsh> USE fgedudb;
cqlsh:fgedudb>

# 创建SAI索引
# 在email列创建SAI索引
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_users_email_sai
… ON fgedu_users (email)
… USING ‘StorageAttachedIndex’;

# 在created_at列创建SAI索引(支持范围查询)
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_orders_created_sai
… ON fgedu_orders (created_at)
… USING ‘StorageAttachedIndex’;

# 在status列创建SAI索引
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_orders_status_sai
… ON fgedu_orders (status)
… USING ‘StorageAttachedIndex’;

# 查看索引
cqlsh:fgedudb> DESCRIBE TABLE fgedu_users;

CREATE TABLE fgedudb.fgedu_users (
user_id uuid PRIMARY KEY,
email text,
user_name text,

) WITH …
CREATE CUSTOM INDEX idx_users_email_sai ON fgedudb.fgedu_users (email)
USING ‘StorageAttachedIndex’;

# 验证索引
cqlsh:fgedudb> SELECT * FROM system_schema.indexes
… WHERE keyspace_name = ‘fgedudb’;

keyspace_name | table_name | index_name | kind | options
—————+————–+————————-+——–+———
fgedudb | fgedu_users | idx_users_email_sai | CUSTOM | {‘class_name’: ‘org.apache.cassandra.index.sai.StorageAttachedIndex’}
fgedudb | fgedu_orders | idx_orders_created_sai | CUSTOM | {‘class_name’: ‘org.apache.cassandra.index.sai.StorageAttachedIndex’}
fgedudb | fgedu_orders | idx_orders_status_sai | CUSTOM | {‘class_name’: ‘org.apache.cassandra.index.sai.StorageAttachedIndex’}

(3 rows)

3.1.2 Cassandra数据库使用SAI索引查询

# 使用SAI索引查询

# 等值查询
cqlsh:fgedudb> SELECT * FROM fgedu_users
… WHERE email = ‘zhangsan@fgedu.net.cn’;

user_id | email | user_name | created_at
————————————–+———————-+———–+———————————-
8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | zhangsan@fgedu.net.cn | zhangsan | 2024-01-15 10:30:00.123000+0000

(1 row)

# 范围查询
cqlsh:fgedudb> SELECT * FROM fgedu_orders
… WHERE created_at >= ‘2024-01-01’
… AND created_at < '2024-02-01' ... LIMIT 100; order_id | created_at | status | user_id --------------------------------------+----------------------------------+---------+-------------------------------------- 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | 2024-01-15 10:30:00.123000+0000 | CREATED | 9f7g8h9i-0j1k-2l3m-4n5o-6p7q8r9s0t1u (1 row) # 多条件查询 cqlsh:fgedudb> SELECT * FROM fgedu_orders
… WHERE status = ‘PAID’
… AND created_at >= ‘2024-01-01’
… LIMIT 100;

# 组合查询(分区键+索引)
cqlsh:fgedudb> SELECT * FROM fgedu_orders
… WHERE user_id = 9f7g8h9i-0j1k-2l3m-4n5o-6p7q8r9s0t1u
… AND status = ‘PAID’;

# 使用EXPLAIN分析查询
cqlsh:fgedudb> EXPLAIN SELECT * FROM fgedu_users WHERE email = ‘test@fgedu.net.cn’;

# 删除SAI索引
cqlsh:fgedudb> DROP INDEX IF EXISTS idx_users_email_sai;

3.2 Cassandra数据库SASI索引实战

Cassandra数据库SASI索引实战:

3.2.1 Cassandra数据库创建SASI索引

# 创建SASI索引

# 创建PREFIX模式索引(前缀匹配)
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_users_name_prefix
… ON fgedu_users (user_name)
… USING ‘org.apache.cassandra.index.sasi.SASIIndex’
… WITH OPTIONS = {
… ‘mode’: ‘PREFIX’,
… ‘case_sensitive’: ‘false’
… };

# 创建CONTAINS模式索引(包含匹配)
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_users_name_contains
… ON fgedu_users (user_name)
… USING ‘org.apache.cassandra.index.sasi.SASIIndex’
… WITH OPTIONS = {
… ‘mode’: ‘CONTAINS’,
… ‘analyzer_class’: ‘org.apache.cassandra.index.sasi.analyzer.StandardAnalyzer’,
… ‘case_sensitive’: ‘false’
… };

# 创建SPARSE模式索引(稀疏索引,适用于高基数列)
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_users_id_sparse
… ON fgedu_users (user_id)
… USING ‘org.apache.cassandra.index.sasi.SASIIndex’
… WITH OPTIONS = {
… ‘mode’: ‘SPARSE’
… };

# 查看索引
cqlsh:fgedudb> DESCRIBE TABLE fgedu_users;

3.2.2 Cassandra数据库使用SASI索引查询

# 使用SASI索引查询

# 前缀匹配查询
cqlsh:fgedudb> SELECT * FROM fgedu_users
… WHERE user_name LIKE ‘张%’;

user_id | user_name | email
————————————–+———–+——————–
8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | 张三 | zhangsan@fgedu.cn
9f7g8h9i-0j1k-2l3m-4n5o-6p7q8r9s0t1u | 张四 | zhangsi@fgedu.cn

(2 rows)

# 包含匹配查询
cqlsh:fgedudb> SELECT * FROM fgedu_users
… WHERE user_name LIKE ‘%三%’;

user_id | user_name | email
————————————–+———–+——————–
8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | 张三 | zhangsan@fgedu.cn

(1 row)

# 范围查询
cqlsh:fgedudb> SELECT * FROM fgedu_users
… WHERE user_name >= ‘张’
… AND user_name < '赵'; # 组合查询 cqlsh:fgedudb> SELECT * FROM fgedu_users
… WHERE user_name LIKE ‘%三%’
… AND email LIKE ‘%@fgedu.cn’;

# 删除SASI索引
cqlsh:fgedudb> DROP INDEX IF EXISTS idx_users_name_contains;

3.3 Cassandra数据库查询优化实战

Cassandra数据库查询优化实战:

3.3.1 Cassandra数据库查询性能分析

# 查询性能分析

# 1. 使用TRACING分析查询
cqlsh:fgedudb> TRACING ON;
cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE user_id = ?;

Tracing session: 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b

activity | timestamp | source | source_elapsed
—————————————————–+—————————-+————–+—————-
Execute CQL3 | 2024-01-15 10:30:00.123000 | 192.168.1.101 | 0
Parsing SELECT * FROM … | 2024-01-15 10:30:00.123100 | 192.168.1.101 | 100
preparing statement | 2024-01-15 10:30:00.123200 | 192.168.1.101 | 200
determining replicas for query | 2024-01-15 10:30:00.123300 | 192.168.1.101 | 300
sending request to … | 2024-01-15 10:30:00.123400 | 192.168.1.101 | 400
reading data | 2024-01-15 10:30:00.123500 | 192.168.1.101 | 500
sending response | 2024-01-15 10:30:00.123600 | 192.168.1.101 | 600
processing result | 2024-01-15 10:30:00.123700 | 192.168.1.101 | 700

(8 rows)

# 关闭TRACING
cqlsh:fgedudb> TRACING OFF;

# 2. 使用nodetool分析
# 查看表统计信息
# nodetool tablestats fgedudb.fgedu_users

Total number of tables: 1
————————-
Keyspace : fgedudb
Table: fgedu_users
SSTable count: 5
Space used (live): 1073741824
Space used (total): 1073741824
Number of keys (estimate): 1000000
Memtable cell count: 10000
Memtable data size: 10485760
Memtable switch count: 10
Read count: 100000
Read latency: 0.123 ms
Write count: 500000
Write latency: 0.045 ms
Pending flushes: 0

# 3. 使用系统表分析
cqlsh:fgedudb> SELECT * FROM system_schema.columns
… WHERE keyspace_name = ‘fgedudb’
… AND table_name = ‘fgedu_users’;

3.3.2 Cassandra数据库查询优化实施

# 查询优化实施

# 1. 优化分区键查询
# 原查询
SELECT * FROM fgedu_orders WHERE user_id = ?;

# 优化后(添加聚簇键范围)
SELECT * FROM fgedu_orders
WHERE user_id = ?
AND order_time >= ?
AND order_time < ?; # 2. 优化索引查询 # 原查询(全表扫描) SELECT * FROM fgedu_users WHERE email = ?; # 优化后(使用索引) CREATE CUSTOM INDEX idx_email_sai ON fgedu_users (email) USING 'StorageAttachedIndex'; SELECT * FROM fgedu_users WHERE email = ?; # 3. 优化分页查询 # 原查询 SELECT * FROM fgedu_logs LIMIT 10000; # 优化后(使用分页状态) # 应用代码实现 Statement statement = QueryBuilder.select() .from("fgedu_logs") .setFetchSize(100); ResultSet results = session.execute(statement); while (!results.isFullyFetched()) { results.fetchMoreResults(); for (Row row : results) { // 处理数据 } } # 4. 优化并行查询 # 原查询(串行) for (UUID userId : userIds) { ResultSet results = session.execute( "SELECT * FROM fgedu_users WHERE user_id = ?", userId ); } # 优化后(并行) List futures = new ArrayList<>();
for (UUID userId : userIds) {
futures.add(session.executeAsync(
“SELECT * FROM fgedu_users WHERE user_id = ?”, userId
));
}
for (ResultSetFuture future : futures) {
ResultSet results = future.get();
// 处理结果
}

# 5. 优化一致性级别
# 原查询
CONSISTENCY QUORUM;
SELECT * FROM fgedu_users WHERE user_id = ?;

# 优化后(降低一致性级别)
CONSISTENCY LOCAL_ONE;
SELECT * FROM fgedu_users WHERE user_id = ?;

优化建议:查询优化需要结合具体业务场景。使用TRACING分析查询性能,找出瓶颈。优先优化分区键设计,合理使用索引,避免全表扫描。更多学习教程公众号风哥教程itpux_com

Part04-生产案例与实战讲解

4.1 Cassandra数据库用户查询优化实战

Cassandra数据库用户查询优化实战案例:

4.1.1 Cassandra数据库用户查询场景分析

# 用户查询场景

# 场景1: 根据用户ID查询
# 最优方案:分区键查询
cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE user_id = ?;

# 性能:毫秒级
# 说明:直接定位分区,效率最高

# 场景2: 根据邮箱查询
# 方案1:创建索引
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_email_sai ON fgedu_users (email)
… USING ‘StorageAttachedIndex’;

cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE email = ?;

# 方案2:创建邮箱索引表
cqlsh:fgedudb> CREATE TABLE fgedu_users_by_email (
… email text PRIMARY KEY,
… user_id uuid
… );

# 两步查询
cqlsh:fgedudb> SELECT user_id FROM fgedu_users_by_email WHERE email = ?;
cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE user_id = ?;

# 场景3: 根据用户名模糊查询
# 方案:创建SASI索引
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_name_sasi ON fgedu_users (user_name)
… USING ‘org.apache.cassandra.index.sasi.SASIIndex’
… WITH OPTIONS = {‘mode’: ‘CONTAINS’};

cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE user_name LIKE ‘%张%’;

# 场景4: 根据状态查询
# 方案:创建二级索引(低基数列)
cqlsh:fgedudb> CREATE INDEX idx_status ON fgedu_users (status);

cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE status = ‘ACTIVE’;

4.1.2 Cassandra数据库用户查询优化实施

# 用户查询优化实施

# 1. 创建必要的索引
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_users_email_sai ON fgedu_users (email)
… USING ‘StorageAttachedIndex’;

cqlsh:fgedudb> CREATE CUSTOM INDEX idx_users_phone_sai ON fgedu_users (phone)
… USING ‘StorageAttachedIndex’;

cqlsh:fgedudb> CREATE INDEX idx_users_status ON fgedu_users (status);

# 2. 创建查询表
# 按创建时间查询用户
cqlsh:fgedudb> CREATE TABLE fgedu_users_by_created (
… created_date date,
… created_time timestamp,
… user_id uuid,
… user_name text,
… email text,
… PRIMARY KEY (created_date, created_time)
… ) WITH CLUSTERING ORDER BY (created_time DESC);

# 按地区查询用户
cqlsh:fgedudb> CREATE TABLE fgedu_users_by_region (
… region text,
… user_id uuid,
… user_name text,
… email text,
… PRIMARY KEY (region, user_id)
… );

# 3. 查询性能测试
# 开启TRACING
cqlsh:fgedudb> TRACING ON;

# 测试分区键查询
cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE user_id = ?;
# 预期:1-5ms

# 测试索引查询
cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE email = ?;
# 预期:5-20ms

# 测试模糊查询
cqlsh:fgedudb> SELECT * FROM fgedu_users WHERE user_name LIKE ‘%张%’;
# 预期:20-100ms

# 关闭TRACING
cqlsh:fgedudb> TRACING OFF;

# 4. 监控查询性能
# 查看慢查询日志
# grep “slow query” /cassandra/logs/system.log

# 分析查询统计
# nodetool tablestats fgedudb.fgedu_users

4.2 Cassandra数据库订单查询优化实战

Cassandra数据库订单查询优化实战案例:

4.2.1 Cassandra数据库订单查询场景分析

# 订单查询场景

# 场景1: 根据订单ID查询
# 最优方案:分区键查询
cqlsh:fgedudb> SELECT * FROM fgedu_orders WHERE order_id = ?;

# 场景2: 根据用户ID查询订单列表
# 方案:分区键+聚簇键查询
cqlsh:fgedudb> SELECT * FROM fgedu_orders
… WHERE user_id = ?
… ORDER BY order_time DESC
… LIMIT 20;

# 场景3: 根据订单状态查询
# 方案:创建索引表
cqlsh:fgedudb> CREATE TABLE fgedu_orders_by_status (
… status text,
… order_time timestamp,
… order_id uuid,
… user_id uuid,
… amount decimal,
… PRIMARY KEY (status, order_time)
… ) WITH CLUSTERING ORDER BY (order_time DESC);

cqlsh:fgedudb> SELECT * FROM fgedu_orders_by_status
… WHERE status = ‘PAID’
… LIMIT 100;

# 场景4: 根据时间范围查询
# 方案:创建时间分区表
cqlsh:fgedudb> CREATE TABLE fgedu_orders_by_date (
… order_date date,
… order_time timestamp,
… order_id uuid,
… user_id uuid,
… amount decimal,
… status text,
… PRIMARY KEY (order_date, order_time)
… ) WITH CLUSTERING ORDER BY (order_time DESC);

cqlsh:fgedudb> SELECT * FROM fgedu_orders_by_date
… WHERE order_date = ‘2024-01-15’
… LIMIT 100;

4.2.2 Cassandra数据库订单查询优化实施

# 订单查询优化实施

# 1. 创建索引表
# 按状态查询
cqlsh:fgedudb> CREATE TABLE fgedu_orders_by_status (
… status text,
… created_at timestamp,
… order_id uuid,
… user_id uuid,
… amount decimal,
… PRIMARY KEY (status, created_at)
… ) WITH CLUSTERING ORDER BY (created_at DESC);

# 按日期查询
cqlsh:fgedudb> CREATE TABLE fgedu_orders_by_date (
… order_date date,
… order_time timestamp,
… order_id uuid,
… user_id uuid,
… amount decimal,
… status text,
… PRIMARY KEY (order_date, order_time)
… ) WITH CLUSTERING ORDER BY (order_time DESC);

# 2. 数据同步写入
cqlsh:fgedudb> BEGIN BATCH
… INSERT INTO fgedu_orders (order_id, user_id, order_time, amount, status)
… VALUES (?, ?, ?, ?, ‘CREATED’);
… INSERT INTO fgedu_orders_by_status (status, created_at, order_id, user_id, amount)
… VALUES (‘CREATED’, ?, ?, ?, ?);
… INSERT INTO fgedu_orders_by_date (order_date, order_time, order_id, user_id, amount, status)
… VALUES (?, ?, ?, ?, ?, ‘CREATED’);
… APPLY BATCH;

# 3. 查询性能测试
# 开启TRACING
cqlsh:fgedudb> TRACING ON;

# 测试用户订单查询
cqlsh:fgedudb> SELECT * FROM fgedu_orders
… WHERE user_id = ?
… ORDER BY order_time DESC
… LIMIT 20;

# 测试状态查询
cqlsh:fgedudb> SELECT * FROM fgedu_orders_by_status
… WHERE status = ‘PAID’
… LIMIT 100;

# 测试日期查询
cqlsh:fgedudb> SELECT * FROM fgedu_orders_by_date
… WHERE order_date = ‘2024-01-15’
… LIMIT 100;

# 关闭TRACING
cqlsh:fgedudb> TRACING OFF;

# 4. 查询优化脚本
#!/bin/bash
# order_query_optimize.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn

# 统计订单查询性能
echo “订单查询性能统计:”
echo “==================”

# 统计分区键查询
echo “分区键查询:”
cqlsh -e “SELECT COUNT(*) FROM fgedudb.fgedu_orders WHERE user_id = ?” 2>&1 | grep “Query”

# 统计索引查询
echo “索引查询:”
cqlsh -e “SELECT COUNT(*) FROM fgedudb.fgedu_orders_by_status WHERE status = ‘PAID'” 2>&1 | grep “Query”

echo “统计完成”

4.3 Cassandra数据库日志查询优化实战

Cassandra数据库日志查询优化实战案例:

4.3.1 Cassandra数据库日志查询场景分析

# 日志查询场景

# 场景1: 查询最近日志
# 方案:分区键+聚簇键查询
cqlsh:fgedudb> SELECT * FROM fgedu_logs
… WHERE log_date = ‘2024-01-15’
… ORDER BY log_time DESC
… LIMIT 100;

# 场景2: 查询特定级别日志
# 方案:创建索引表
cqlsh:fgedudb> CREATE TABLE fgedu_logs_by_level (
… log_level text,
… log_date date,
… log_time timestamp,
… log_id uuid,
… message text,
… PRIMARY KEY ((log_level, log_date), log_time)
… ) WITH CLUSTERING ORDER BY (log_time DESC);

cqlsh:fgedudb> SELECT * FROM fgedu_logs_by_level
… WHERE log_level = ‘ERROR’
… AND log_date = ‘2024-01-15’
… LIMIT 100;

# 场景3: 查询特定服务日志
# 方案:创建服务分区表
cqlsh:fgedudb> CREATE TABLE fgedu_logs_by_service (
… service_name text,
… log_date date,
… log_time timestamp,
… log_id uuid,
… log_level text,
… message text,
… PRIMARY KEY ((service_name, log_date), log_time)
… ) WITH CLUSTERING ORDER BY (log_time DESC);

cqlsh:fgedudb> SELECT * FROM fgedu_logs_by_service
… WHERE service_name = ‘user-service’
… AND log_date = ‘2024-01-15’
… LIMIT 100;

# 场景4: 查询包含关键字的日志
# 方案:创建SASI索引
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_message_sasi ON fgedu_logs (message)
… USING ‘org.apache.cassandra.index.sasi.SASIIndex’
… WITH OPTIONS = {‘mode’: ‘CONTAINS’};

cqlsh:fgedudb> SELECT * FROM fgedu_logs
… WHERE message LIKE ‘%error%’
… LIMIT 100;

4.3.2 Cassandra数据库日志查询优化实施

# 日志查询优化实施

# 1. 创建日志表结构
# 主日志表
cqlsh:fgedudb> CREATE TABLE fgedu_logs (
… log_date date,
… log_time timestamp,
… log_id uuid,
… log_level text,
… service_name text,
… logger text,
… message text,
… stack_trace text,
… PRIMARY KEY (log_date, log_time)
… ) WITH CLUSTERING ORDER BY (log_time DESC)
… AND default_time_to_live = 604800; — 7天自动过期

# 按级别分表
cqlsh:fgedudb> CREATE TABLE fgedu_logs_by_level (
… log_level text,
… log_date date,
… log_time timestamp,
… log_id uuid,
… service_name text,
… message text,
… PRIMARY KEY ((log_level, log_date), log_time)
… ) WITH CLUSTERING ORDER BY (log_time DESC)
… AND default_time_to_live = 2592000; — 30天自动过期

# 2. 创建索引
cqlsh:fgedudb> CREATE CUSTOM INDEX idx_service_sai ON fgedu_logs (service_name)
… USING ‘StorageAttachedIndex’;

cqlsh:fgedudb> CREATE CUSTOM INDEX idx_message_sasi ON fgedu_logs (message)
… USING ‘org.apache.cassandra.index.sasi.SASIIndex’
… WITH OPTIONS = {‘mode’: ‘CONTAINS’};

# 3. 查询性能测试
# 开启TRACING
cqlsh:fgedudb> TRACING ON;

# 测试日期查询
cqlsh:fgedudb> SELECT * FROM fgedu_logs
… WHERE log_date = ‘2024-01-15’
… LIMIT 100;

# 测试级别查询
cqlsh:fgedudb> SELECT * FROM fgedu_logs_by_level
… WHERE log_level = ‘ERROR’
… AND log_date = ‘2024-01-15’;

# 测试关键字查询
cqlsh:fgedudb> SELECT * FROM fgedu_logs
… WHERE message LIKE ‘%exception%’
… LIMIT 100;

# 关闭TRACING
cqlsh:fgedudb> TRACING OFF;

# 4. 日志清理
# 自动清理(通过TTL)
# 手动清理
cqlsh:fgedudb> DELETE FROM fgedu_logs WHERE log_date < '2024-01-01';

风哥提示:日志查询优化需要平衡查询效率和存储成本。使用TTL自动清理过期日志,创建必要的索引表支持常用查询。监控日志表大小,避免大分区问题。from Cassandra视频:www.itpux.com

Part05-风哥经验总结与分享

5.1 Cassandra数据库索引最佳实践

Cassandra数据库索引最佳实践总结:

  • 优先优化表结构:索引是补充手段,优先通过表结构设计解决查询需求
  • 选择合适的索引类型:根据查询场景选择SAI、SASI或二级索引
  • 控制索引数量:单表索引不超过3个,避免过多索引影响写入性能
  • 监控索引性能:定期监控索引大小、查询性能和维护开销
  • 及时清理无效索引:删除不再使用的索引,减少维护成本
  • 测试验证:在生产环境部署前充分测试索引效果

5.2 Cassandra数据库查询最佳实践

# 查询最佳实践

# 1. 分区键优先
– 查询必须包含分区键
– 避免全表扫描
– 合理设计分区键

# 2. 使用聚簇键
– 利用聚簇键排序
– 支持范围查询
– 减少扫描行数

# 3. 合理使用索引
– 选择合适的索引类型
– 监控索引性能
– 及时维护索引

# 4. 分页查询
– 使用LIMIT分页
– 使用分页状态
– 避免大结果集

# 5. 并行查询
– 使用异步查询
– 并行查询多个分区
– 提高吞吐量

# 6. 一致性级别
– 选择合适的一致性级别
– 平衡一致性和性能
– 使用本地一致性

# 7. 避免ALLOW FILTERING
– 重新设计表结构
– 创建必要的索引
– 使用查询表

# 8. 监控查询性能
– 使用TRACING分析
– 监控慢查询
– 定期优化

5.3 Cassandra数据库性能监控工具

Cassandra数据库性能监控工具推荐:

5.3.1 Cassandra数据库监控工具

# 性能监控工具

# 1. nodetool
# 查看集群状态
# nodetool status

# 查看表统计
# nodetool tablestats fgedudb.fgedu_users

# 查看表直方图
# nodetool tablehistograms fgedudb.fgedu_users

# 查看压缩统计
# nodetool compactionstats

# 查看GC统计
# nodetool gcstats

# 2. cqlsh TRACING
# 开启查询追踪
cqlsh> TRACING ON;
cqlsh> SELECT * FROM fgedu_users WHERE user_id = ?;
cqlsh> TRACING OFF;

# 3. 系统日志
# 查看慢查询日志
# grep “slow query” /cassandra/logs/system.log

# 查看错误日志
# grep “ERROR” /cassandra/logs/system.log

# 4. JMX监控
# 使用JConsole或VisualVM连接
# 监控JVM指标

# 5. DataStax OpsCenter
# DataStax官方监控工具
# 图形化界面
# 支持告警和报告

# 6. Prometheus + Grafana
# 开源监控方案
# 支持自定义指标
# 图形化展示

# 7. 第三方工具
– Instaclustr
– DataStax Astra
– ScyllaDB Monitoring

监控建议:建立完善的监控体系,定期检查性能指标。设置告警阈值,及时发现和解决问题。保留历史数据,用于趋势分析和容量规划。

本文档详细介绍了Cassandra数据库索引与查询优化实战,包括索引概述、索引类型、查询优化概念、索引设计原则、索引创建策略、查询优化策略、SAI索引实战、SASI索引实战、查询优化实战、用户查询优化实战、订单查询优化实战、日志查询优化实战、索引最佳实践、查询最佳实践、性能监控工具等内容。通过学习本文档,读者可以掌握Cassandra数据库索引和查询优化技能,为应用开发打下坚实基础。

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息