我正在分析使用Cassandra的应用程序,结果发现读取是瓶颈。仔细观察它们似乎已经走了很久,我真的很感激帮助理解为什么。
应用程序始终读取给定分区键的整个行集(查询的格式为SELECT * FROM table WHERE partition_key = ?
)。不出所料,读取时间为O(number of rows for partition key)
,但是常数似乎很高。在检查了查询计划之后,事实证明大部分时间花费在"合并来自mem和sstables"的数据上。
对于~5000行的分区键,此步骤需要200ms,其中一行包含9列,并且小于100字节。考虑到SSD的读取吞吐量,应该立即按顺序读取0.5MB。
实际上,我怀疑这与I / O完全不同。这台机器曾经有一个旋转的磁盘,用现在的SSD替换了。此更改对查询性能没有影响。我认为Cassandra处理中涉及的内容或它如何读取磁盘数据会导致此操作非常昂贵。
从多个SSTable合并或迭代逻辑删除的单元格并不能解释这一点。首先,它应该花费几毫秒,其中所有这一切始终如一地发生,无论它是2或4个SSTables以及是否存在逻辑删除的单元格。
提供一些背景信息:
硬件:运行Cassandra的机器是8核,裸机和SSD支持。我从机器上的cqlsh查询它,数据存储在本地。没有其他负载,看着iostats,也几乎没有任何i / o。
数据模型:分区键PK
属于text
类型,主键是分区键和bigint
列的组合K
,其余的是7个可变列。架构创建命令如下所示。
CREATE TABLE inboxes (
PK text,
K bigint,
A boolean,
B boolean,
C boolean,
D boolean,
E bigint,
E bigint,
F int,
PRIMARY KEY (PK, K)
) WITH CLUSTERING ORDER BY (K DESC));
这是一个示例跟踪,涉及3个SSTable,一个相当多的墓碑。
activity | timestamp | source | source_elapsed
-------------------------------------------------------------------------------------------+--------------+-------------+----------------
execute_cql3_query | 03:14:07,507 | 10.161.4.77 | 0
Parsing select * from table where PK = 'key_value' LIMIT 10000;| 03:14:07,508 | 10.161.4.77 | 123
Preparing statement | 03:14:07,508 | 10.161.4.77 | 244
Executing single-partition query on table | 03:14:07,509 | 10.161.4.77 | 1155
Acquiring sstable references | 03:14:07,509 | 10.161.4.77 | 1173
Merging memtable tombstones | 03:14:07,509 | 10.161.4.77 | 1195
Key cache hit for sstable 2906 | 03:14:07,509 | 10.161.4.77 | 1231
Seeking to partition beginning in data file | 03:14:07,509 | 10.161.4.77 | 1240
Key cache hit for sstable 1533 | 03:14:07,509 | 10.161.4.77 | 1550
Seeking to partition beginning in data file | 03:14:07,509 | 10.161.4.77 | 1561
Key cache hit for sstable 1316 | 03:14:07,509 | 10.161.4.77 | 1867
Seeking to partition beginning in data file | 03:14:07,509 | 10.161.4.77 | 1878
Merging data from memtables and 3 sstables | 03:14:07,510 | 10.161.4.77 | 2180
Read 5141 live and 1944 tombstoned cells | 03:14:07,646 | 10.161.4.77 | 138734
Request complete | 03:14:07,742 | 10.161.4.77 | 235030
答案 0 :(得分:2)
你不只是“按顺序读取0.5MB”,你要求Cassandra将其变成行,过滤掉墓碑(删除的行),并将其转换为结果集。每行0.04ms非常合理;对于整个查询,我的经验法则是每10行0.5毫秒。
请记住,Cassandra针对适合在线申请的简短请求进行了优化;典型地,10到100行结果集。单个查询中没有并行化。