【发布时间】:2014-06-23 17:03:59
【问题描述】:
我正在分析一个使用 Cassandra 的应用程序,结果发现读取是瓶颈。经过仔细检查,它们似乎需要很长时间,我真的很感激能帮助我理解原因。
应用程序总是读取给定分区键的整组行(查询格式为SELECT * FROM table WHERE partition_key = ?)。不出所料,阅读时间是O(number of rows for partition key),但是这个常数似乎太高了。在检查了查询计划之后,结果发现大部分时间都花在了“合并来自 mem 和 sstables 的数据”上。
对于约 5000 行的分区键,此步骤需要 200 多毫秒,其中一行由 9 列组成,并且小于 100 字节。考虑到 SSD 的读取吞吐量,顺序读取 0.5MB 应该会立即发生。
实际上,我怀疑这根本与 I/O 有关。这台机器曾经有一个旋转磁盘,现在换成了 SSD。更改对查询性能没有影响。我认为 Cassandra 处理或它如何读取磁盘数据的方式非常复杂,这使得该操作非常昂贵。
从多个 SSTable 合并或迭代墓碑单元并不能解释这一点。首先,它应该花费几毫秒,其次这一切都在持续发生,无论是 2 个还是 4 个 SSTable,以及是否有墓碑单元。
提供一些背景知识:
硬件: 运行 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
【问题讨论】:
-
尽可能粘贴跟踪
-
@RussS 使用示例跟踪更新了一个问题。这个实际上要快一点,但在我看来,调用的最后两个元素仍然需要很长时间。
-
1.使用某些现有分区 ID 时的响应时间是多少? Cassandra 必须遍历内存部分、sstables 和 tombsones,并且它还使用布隆过滤器,这可能需要一些时间才能找到任何东西。 2. 你的数据结构是什么?所有数据中是否有很多更新、删除等。由于 cassandra 中的一切都是不可变的,因此可以触摸很多项目来发现什么都没有找到。
-
@MartinPodval 几乎没有任何删除,有不少更新/插入。正如我所说的 i/o 并没有真正注册(所以那里没有瓶颈),盒子上的负载是最小的,在我给出的跟踪中,当发现数据时读取和处理需要时间。您阅读 200 毫秒。作为比较,在同一类盒子上,以 5000req/s 的速度对 5000 个对象进行排序,其 p99 为 7ms。
-
你用的是什么版本?
标签: database performance cassandra latency nosql