【发布时间】:2017-08-27 09:41:22
【问题描述】:
我正在处理单个节点。我有下表来存储文档列表:
CREATE TABLE my_keyspace.document (
status text,
date timestamp,
doc_id text,
raw_content text,
title text,
PRIMARY KEY (status, date, doc_id)
) WITH CLUSTERING ORDER BY (date ASC, doc_id ASC)
AND bloom_filter_fp_chance = 0.01
AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
AND comment = ''
AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
AND crc_check_chance = 1.0
AND dclocal_read_repair_chance = 0.1
AND default_time_to_live = 0
AND gc_grace_seconds = 0
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND read_repair_chance = 0.0
AND speculative_retry = '99PERCENTILE';
CREATE INDEX doc_id_idx ON my_keyspace.document (doc_id);
我正在做很多查询,例如:
SELECT * FROM my_keyspace.document WHERE status='PROCESSED' AND data>=start_date AND data<=end_date;
由于某种原因它非常慢,起初我收到的警告是这样的:
[2016-07-26 18:10:46] {cassandra.protocol:378} WARNING - Server warning: Read 5000 live rows and 19999 tombstone cells for query SELECT * FROM my_keyspace.document WHERE token(status) >= token(PROCESSED) AND token(status) <= token(PROCESSED) AND date >= 2016-07-08 02:00+0200 AND date <= 2016-07-23 01:59+0200 LIMIT 5000 (see tombstone_warn_threshold)
[2016-07-26 18:10:52] {cassandra.protocol:378} WARNING - Server warning: Read 5000 live rows and 19999 tombstone cells for query SELECT * FROM my_keyspace.document WHERE token(status) >= token(PROCESSED) AND token(status) <= token(PROCESSED) AND date >= 2016-07-08 02:00+0200 AND date <= 2016-07-23 01:59+0200 LIMIT 5000 (see tombstone_warn_threshold)
认为这个问题与我做的墓碑太多有关:
ALTER TABLE my_keyspace.document WITH gc_grace_seconds = '0';
然后:
nodetool compact my_keyspace document
现在我没有任何警告,但查询仍然很慢并且经常超时。任何日志中都没有显示有关超时的消息。我拥有的文档数量大约是 200k 实例。这些文件在 20 天内分发,每天约有 4500 个文件有status='PROCESSED'。查询回答时间因日期范围而异:一天时间范围约为 3 秒,4 天时间范围为 15 秒,超时时间为 2 周。另外,我禁用了交换。我使用的 Cassandra 版本是 3.5。
最近我注意到,使用精确的列而不是 * 来提取可以稍微缩短响应时间,但系统仍然太慢。
编辑:Reveka 提出的计算分区大小
所以,遵循公式:
- 行数 = 20 * 4500 = 90,000
- 列数 = 19
- 主键数 = 3
- 静态列数 = 0
所以值的数量是 90000*(19-3)=1,440,000
对于分区的大小,我估计约为 1.2GB。
这可能有点大。但是如何修改我的分区键以在拥有较小分区的同时仍然能够执行相同的范围查询?我可以有一个复合分区键,其中包含status 和从date 中提取的日期,但我不必在能够按范围查询之前指定日期:
SELECT * FROM my_keyspace.document WHERE status='PROCESSED' AND day='someday' AND date>='start_date' AND date<='end_date';
这迫使我每天进行一次查询。
【问题讨论】: