Performance 对于Cassandra,为什么在下面的布局中1000次运算/秒会产生400MB/s的I/O?
在一个3.3万亿的记录数据集上,这是一个读操作繁重的工作负载(85%读,15%写),我正在从SATA SSD(最大化控制器)中以450MB/秒的速度读取数据,但仅获得约1000次操作/秒。我不认为它应该做那么多的I/O,但我对Cassandra是新手,不太明白它为什么要这么做Performance 对于Cassandra,为什么在下面的布局中1000次运算/秒会产生400MB/s的I/O?,performance,cassandra,performance-testing,Performance,Cassandra,Performance Testing,在一个3.3万亿的记录数据集上,这是一个读操作繁重的工作负载(85%读,15%写),我正在从SATA SSD(最大化控制器)中以450MB/秒的速度读取数据,但仅获得约1000次操作/秒。我不认为它应该做那么多的I/O,但我对Cassandra是新手,不太明白它为什么要这么做 Keyspace: stresscql Read Count: 81263974 Read Latency: 37.271172120563534 ms. Write Count: 18576806
Keyspace: stresscql
Read Count: 81263974
Read Latency: 37.271172120563534 ms.
Write Count: 18576806
Write Latency: 0.01787069736315274 ms.
Pending Flushes: 0
Table: u
SSTable count: 251
SSTables in each level: [3, 0, 0, 0, 0, 0, 0, 0, 0]
Space used (live): 1712307458381
Space used (total): 1712307458381
Space used by snapshots (total): 0
Off heap memory used (total): 3358807452
SSTable Compression Ratio: 0.6798834918759787
Number of keys (estimate): 3354476152
Memtable cell count: 0
Memtable data size: 0
Memtable off heap memory used: 0
Memtable switch count: 10
Local read count: 81263974
Local read latency: 40.886 ms
Local write count: 18576806
Local write latency: 0.020 ms
Pending flushes: 0
Bloom filter false positives: 0
Bloom filter false ratio: 0.00000
Bloom filter space used: 2097321112
Bloom filter off heap memory used: 2715609520
Index summary off heap memory used: 633723580
Compression metadata off heap memory used: 9474352
Compacted partition minimum bytes: 51
Compacted partition maximum bytes: 72
Compacted partition mean bytes: 72
Average live cells per slice (last five minutes): 1.0000004430007106
Maximum live cells per slice (last five minutes): 10
Average tombstones per slice (last five minutes): 1.0
Maximum tombstones per slice (last five minutes): 1
### DML ###
keyspace: stresscql
keyspace_definition: |
CREATE KEYSPACE stresscql WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
table: u
table_definition: |
CREATE TABLE IF NOT EXISTS u (
c uuid,
f bigint,
i boolean,
bl boolean,
t timestamp,
PRIMARY KEY(c,f, i)
) WITH compaction = { 'class': 'SizeTieredCompactionStrategy' }
AND compression = { 'crc_check_chance' : 1.0, 'sstable_compression' : 'SnappyCompressor' }
### Column Distribution Specifications ###
columnspec:
- name: c
- name: f
- name: i
- name: bl
- name: t
### Batch Ratio Distribution Specifications ###
insert:
partitions: fixed(1)
select: fixed(1)/1
batchtype: UNLOGGED
queries:
selectuser:
cql: select * from u where c = ? and f = ? and i = ?
fields: samerow
newselect:
cql: select bl from u where c = ? and f = ? and i = ?
我也尝试过LeveledCompactionStrategy,这就是我得到的——仍然明显受到I/O的限制:
This row would've been cached (not using row-cache, but whatever other caching happens), since I had to select it to get the guid value for 'c'.
cqlsh> select * from stresscql.u where c = 2953e0ef-44fd-44fb-8d3e-8a2498ae694f;
c | f | i | bl | t
--------------------------------------+-------------+------+------+--------------------------
2953e0ef-44fd-44fb-8d3e-8a2498ae694f | 58180117557 | True | True | 2016-05-07 09:43:07+0000
(1 rows)
Tracing session: dd78f580-32ff-11e6-8746-45b1db7c6f51
activity | timestamp | source | source_elapsed
-------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+--------------+----------------
Execute CQL3 query | 2016-06-15 15:48:39.512000 | 10.7.137.139 | 0
Parsing select * from stresscql.u where c = 2953e0ef-44fd-44fb-8d3e-8a2498ae694f; [SharedPool-Worker-1] | 2016-06-15 15:48:39.512000 | 10.7.137.139 | 92
Preparing statement [SharedPool-Worker-1] | 2016-06-15 15:48:39.512000 | 10.7.137.139 | 208
Executing single-partition query on u [SharedPool-Worker-2] | 2016-06-15 15:48:39.513000 | 10.7.137.139 | 1626
Acquiring sstable references [SharedPool-Worker-2] | 2016-06-15 15:48:39.513000 | 10.7.137.139 | 1677
Partition index with 0 entries found for sstable 15405 [SharedPool-Worker-2] | 2016-06-15 15:48:39.514000 | 10.7.137.139 | 1944
Skipped 0/1 non-slice-intersecting sstables, included 0 due to tombstones [SharedPool-Worker-2] | 2016-06-15 15:48:39.514000 | 10.7.137.139 | 2401
Merging data from memtables and 1 sstables [SharedPool-Worker-2] | 2016-06-15 15:48:39.514000 | 10.7.137.139 | 2445
Request complete | 2016-06-15 15:48:39.543778 | 10.7.137.139 | 31778
Keyspace: stresscql
Read Count: 115672739
Read Latency: 37.24272796733031 ms.
Write Count: 25113006
Write Latency: 0.016802926260599788 ms.
Pending Flushes: 0
Table: user_identified_caller_by_telephone
SSTable count: 847
SSTables in each level: [1, 10, 100, 736, 0, 0, 0, 0, 0]
Space used (live): 2032182537714
Space used (total): 2032182537714
Space used by snapshots (total): 0
Off heap memory used (total): 2540382332
SSTable Compression Ratio: 0.6868674726322842
Number of keys (estimate): 3361569503
Memtable cell count: 1162671
Memtable data size: 42639539
Memtable off heap memory used: 0
Memtable switch count: 12
Local read count: 115672739
Local read latency: 40.854 ms
Local write count: 25113006
Local write latency: 0.019 ms
Pending flushes: 0
Bloom filter false positives: 1
Bloom filter false ratio: 0.00000
Bloom filter space used: 2115703120
Bloom filter off heap memory used: 2115696344
Index summary off heap memory used: 418366956
Compression metadata off heap memory used: 6319032
Compacted partition minimum bytes: 51
Compacted partition maximum bytes: 72
Compacted partition mean bytes: 72
Average live cells per slice (last five minutes): 1.0000007348317013
Maximum live cells per slice (last five minutes): 50
Average tombstones per slice (last five minutes): 1.0
Maximum tombstones per slice (last five minutes): 1
----------------
我可能读错了,但我认为你只创建了一个巨大的分区,这将是非常缓慢的压缩。在新版本(3.6,3.7)中有很多这样的功能,所以一定要使用最新的,因为最近有一些改进会有所帮助。您可能需要更改压力配置文件中的
分区:固定(1)
和选择,以使数据分布更广
可能有一点被压缩所束缚(低默认吞吐量),导致每次读取都必须接触很多SSTABLE。251对于STC来说太多了,因为对于宽分区,它可能必须从每个分区读取
有了这个数据模型和工作负载(撇开压力配置文件问题不谈),您可能应该尝试LeveledCompactionStrategy并提高压缩吞吐量(可以使用nodetool SetCompactionThroughts
进行不同的测试,我会从64开始,但可以上下移动它,看看它如何影响您的工作负载)。压缩将占用更多的IO,但读取将占用更少的IO,这对于您的工作负载来说是更好的。我可能读错了,但我认为您只创建了一个巨大的分区,这将是非常缓慢的压缩。在新版本(3.6,3.7)中有很多这样的功能,所以一定要使用最新的,因为最近有一些改进会有所帮助。您可能需要更改压力配置文件中的分区:固定(1)
和选择,以使数据分布更广
可能有一点被压缩所束缚(低默认吞吐量),导致每次读取都必须接触很多SSTABLE。251对于STC来说太多了,因为对于宽分区,它可能必须从每个分区读取
有了这个数据模型和工作负载(撇开压力配置文件问题不谈),您可能应该尝试LeveledCompactionStrategy并提高压缩吞吐量(可以使用nodetool SetCompactionThroughts
进行不同的测试,我会从64开始,但可以上下移动它,看看它如何影响您的工作负载)。压缩将占用更多的IO,但读取将占用更少的IO,这对于您的工作负载来说是更好的。根据分区:固定(1)部分,意味着在插入批处理期间,一次只插入一个分区键。实际的分区应该基于主键的第一个元素(称为“c”的列)的值/基数,对吗?测试时未运行任何压实。我还使用LeveledCompressionStrategy进行了测试,性能非常相似,但压实时间大大增加了—一次主要压实耗时超过一周!还有一件事需要注意。主要压实后,sstables组合为3个,性能仍如上所述。至于分区——这是单个节点上cassandra的一个实例——分区发挥作用了吗?啊,你说得对(就在统计数据中,我只是看得不够近)。因此,实际上本地写入延迟:0.020 ms
写入似乎很好,它只是读取:本地读取延迟:40.886 ms
。巨型布卢姆过滤器可能是个问题,切换到LCS可以让你基本上摆脱它。甚至可能与索引摘要过于分散的太多分区有关,以mb为单位增加索引摘要容量可能会提供更多空间(我会在BF减少后再做)。除此之外(以及可能的jvm调优),我可能会建议使用像yourkit这样的性能工具。可能不应该在测试中进行重大压缩,因为您永远不会(不应该)在生产中使用它们。(是的,分区位于c
btw)。关于bloom过滤器,它们不是全部存储在内存中吗?对于0%的FP速率和内存中的bloom筛选器,这并不能解释I/O。对于1000 op/s,450MB/s似乎很高。对于宽度小于63字节的列,每次读取约450k。这是我不明白的事情。表示主I/O将扫描分区摘要,然后扫描pkey索引的一小部分,然后根据索引获取数据。我改为“水平”,总吞吐量仍然是~1000 op/s。现在,我将为有关计时/cfstats的问题添加更多信息。根据分区:固定(1)部分,意味着在插入批处理期间,一次只插入一个分区键。实际的分区应该基于主键的第一个元素(称为“c”的列)的值/基数,对吗?测试时未运行任何压实。我还使用LeveledCompressionStrategy进行了测试,性能非常相似,但压实时间大大增加了—一次主要压实耗时超过一周!还有一件事需要注意。主要压实后,sstables组合为3个,性能仍如上所述。至于分区——这是单个节点上cassandra的一个实例——分区发挥作用了吗?啊,你说得对(就在统计数据中,我只是看得不够近)。因此,实际上本地写入延迟:0.020 ms
写入似乎很好,它只是读取:本地读取延迟:40.886 ms
。巨型布卢姆过滤器可能是个问题,切换到LCS可以让你基本上摆脱它。甚至可能与索引摘要过于分散的太多分区有关,以mb为单位增加索引摘要容量可能会提供更多空间