You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cassandra WHERE IN查询性能瓶颈及优化方案咨询

测试背景
  • 集群配置:6节点Cassandra集群,单节点96核CPU、800G内存
  • 测试表结构:
create table if not exists space.table
(
    id          bigint primary key,
    data        frozen<list<float>>,
    updated_at  timestamp
);
  • 数据规模:总计1.5亿行
  • 初始测试现象:
    • 单ID点查(语句为SELECT * FROM space.table WHERE id = X):集群可承载RPS达35万,性能瓶颈先出现在客户端侧,集群本身未到性能上限
    • 单请求携带3000个随机ID的IN查询(语句为SELECT * FROM space.table WHERE id in (X1, X2 ... X3000)):集群最大可承载RPS仅15,超过阈值后Native-Transport-Requests线程池出现大量待处理任务
  • 不同分块大小拉取3000行数据的实测性能:
单请求3000个ID
延迟:5秒
Cassandra侧最大RPS:20

单请求100个ID(拉取3000行共需30次请求)
服务侧350 RPS时(对应Cassandra侧350*30=10500 RPS):q99延迟170ms,q90延迟95ms,q50延迟75ms
Cassandra侧最大RPS:10500

单请求20个ID(拉取3000行共需150次请求)
服务侧250 RPS时(对应Cassandra侧250*150=37500 RPS):q99延迟49ms,q90延迟46ms,q50延迟32ms
服务侧600 RPS时(对应Cassandra侧600*150=90000 RPS):q99延迟190ms,q90延迟180ms,q50延迟148ms
Cassandra侧最大RPS:97500

单请求10个ID(拉取3000行共需300次请求)
服务侧250 RPS时(对应Cassandra侧250*300=75000 RPS):q99延迟48ms,q90延迟31ms,q50延迟11ms
服务侧600 RPS时(对应Cassandra侧600*300=180000 RPS):q99延迟159ms,q90延迟95ms,q50延迟75ms
Cassandra侧最大RPS:195000

单请求5个ID(拉取3000行共需600次请求)
服务侧550 RPS时(对应Cassandra侧550*600=330000 RPS):q99延迟97ms,q90延迟92ms,q50延迟60ms
Cassandra侧最大RPS:363000

单请求1个ID(拉取3000行共需3000次请求)
服务侧190 RPS时(对应Cassandra侧190*3000=570000 RPS):q99延迟49ms,q90延迟43ms,q50延迟30ms
Cassandra侧最大RPS:570000
问题答复

大结果集拉取是否属于Cassandra非推荐用法?

是。Cassandra从设计之初就是面向高吞吐、低延迟的小规模点查场景优化的,内部的线程池配额、内存阈值、超时机制全都是针对小请求设置的。单次请求拉取大结果集、使用上千个ID的长IN查询,会长时间占用协调器节点的内存和线程资源,阻塞其他正常请求的处理,属于典型的误用场景。你观察到的Native-Transport-Requests线程池堆积,就是协调器被大请求占满、无法及时处理新请求的直接表现。

WHERE IN操作是否存在性能层面的设计缺陷?

不存在设计缺陷,本质是使用方式违背了它的设计预期。
IN查询的执行逻辑是:接收请求的协调器节点,会为IN列表里的每个ID计算对应的token,向持有对应数据副本的节点发送子请求,等所有子请求全部返回后,把结果聚合完成再返回给客户端。整个过程中协调器需要持有所有子请求的上下文、临时缓存返回结果,IN列表越长,协调器阻塞的时间就越长、内存占用越高。当IN列表长度达到上千级别时,单个请求就可能占满单个协调器的处理资源,直接拖垮节点。
Cassandra本身默认就对IN列表长度做了安全限制,多数版本默认IN列表元素超过128个就会直接抛错,本质就是防止用户误用长IN查询拖垮集群。

该场景的最佳实践是什么?

你的实测数据已经给出了非常明确的优化方向:

  • 严格控制单次请求的IN列表长度:分块太大直接堵死集群,分块太细会把开销耗在客户端侧的请求序列化、连接维护上。从测试结果看,单请求携带5-20个ID是综合性价比最高的区间——既不会给协调器造成过大的聚合压力,也不会因为拆分过细浪费客户端性能,业务侧吞吐、延迟表现都最优。如果追求Cassandra侧的极限吞吐可以选单ID查询,但要提前评估客户端的性能瓶颈。
  • 开启驱动的token感知负载均衡:拆分后的请求不要全部发往同一个协调器,使用Cassandra官方驱动自带的token感知能力,直接把每个请求发往持有对应数据的副本节点,省去协调器转发、结果聚合的开销,性能还能再提升30%以上。
  • 不要随意调大默认的安全阈值:官方默认的IN列表长度、native transport线程池并发、请求在途数量等限制,都是经过长期生产验证的安全值,随意调大只会大幅提升集群雪崩的风险。
  • 如果有超大规模批量拉取需求(比如一次拉取上万、十万行数据),不要走在线查询接口,改用离线批量扫描工具导出,避免占用在线业务的资源。

相关说明的查阅渠道

  • Cassandra官方文档的查询优化章节,明确标注了长IN查询的性能风险,以及推荐的IN列表长度范围。
  • Cassandra官方配置参数说明中,和native transport线程池、请求阈值、查询限制相关的参数注释里,都有对应的风险提示和配置建议。
  • Cassandra官方维护的各语言驱动文档中,关于查询编写、负载均衡配置的最佳实践章节,有多ID查询的分片、路由相关的明确指引。

内容的提问来源于stack exchange,提问作者Tipok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:33:11