当我不执行 DELETE 时,为什么有时会有 10,000 多个墓碑?
Why do I sometimes have 10,000+ tombstones when I don't do DELETEs?
在修复 Cassandra 节点时,有时会看到很多逻辑删除日志。错误如下所示:
org.apache.cassandra.db.filter.TombstoneOverwhelmingException: Scanned over 100001 tombstone rows during query 'SELECT * FROM my_keyspace.table_foo WHERE token(<my params>) >= token(<my params>) AND token(<my params>) <= 2988334221698479200 LIMIT 2147385647' (last scanned row partition key was ((<my params>), 7c650d21-797e-4476-93d5-b1248e187f22)); query aborted
我读到 here 插入墓碑是将记录标记为已删除的一种方式。但是,我在这个项目中没有看到任何代码对此 table 运行删除 - 只是读取和插入。我缺少什么 - 如何防止这些 TombStoneOverwhelmingExceptions?
这里是 table 定义:
CREATE TABLE my_keyspace.table_foo(
foo1 text,
year int,
month int,
foo2 text,
PRIMARY KEY ((foo1, year, month), foo2)
) WITH CLUSTERING ORDER BY (foo2 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 default_time_to_live = 6912000
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND speculative_retry = '99PERCENTILE';
@anthony,这是我的视角。
- 第一步,不要让墓碑插入table
- 在读取路径中使用完整的主键,这样我们就不必读取墓碑了。数据建模是根据阅读端所需的访问模式设计 table 的关键
- 我们可以调整
min_threshold
并将其设置为 2
以执行一些积极的逻辑删除
- 同样,我们可以调整 common options(例如
unchecked_tombstone_compaction
设置为 true
或其他 properties/options)以更快地驱逐它们
- 我鼓励您查看 类似的 问题和已记录的答案 here
However, I don't see any code in this project that runs a delete on this table - just a read and an insert.
代码可能不是 运行 DELETE
s,但 table 定义告诉 Cassandra 删除任何大于等于 80 天的内容。 TTL 创建墓碑。
AND default_time_to_live = 6912000
因此,时间序列模型中 TTL 背后的想法是,它们通常按时间戳降序排列。最终发生的事情是,大多数用例往往只关心最近的数据,并且按时间戳的降序导致墓碑最终出现在分区的“底部”,在那里它们很少(如果有的话)被查询。
要创建该效果,您需要创建一个新的 table,其定义如下:
PRIMARY KEY ((foo1, year, month), created_time, foo2)
) WITH CLUSTERING ORDER BY (created_time DESC, foo2 ASC)
在修复 Cassandra 节点时,有时会看到很多逻辑删除日志。错误如下所示:
org.apache.cassandra.db.filter.TombstoneOverwhelmingException: Scanned over 100001 tombstone rows during query 'SELECT * FROM my_keyspace.table_foo WHERE token(<my params>) >= token(<my params>) AND token(<my params>) <= 2988334221698479200 LIMIT 2147385647' (last scanned row partition key was ((<my params>), 7c650d21-797e-4476-93d5-b1248e187f22)); query aborted
我读到 here 插入墓碑是将记录标记为已删除的一种方式。但是,我在这个项目中没有看到任何代码对此 table 运行删除 - 只是读取和插入。我缺少什么 - 如何防止这些 TombStoneOverwhelmingExceptions?
这里是 table 定义:
CREATE TABLE my_keyspace.table_foo(
foo1 text,
year int,
month int,
foo2 text,
PRIMARY KEY ((foo1, year, month), foo2)
) WITH CLUSTERING ORDER BY (foo2 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 default_time_to_live = 6912000
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND speculative_retry = '99PERCENTILE';
@anthony,这是我的视角。
- 第一步,不要让墓碑插入table
- 在读取路径中使用完整的主键,这样我们就不必读取墓碑了。数据建模是根据阅读端所需的访问模式设计 table 的关键
- 我们可以调整
min_threshold
并将其设置为2
以执行一些积极的逻辑删除 - 同样,我们可以调整 common options(例如
unchecked_tombstone_compaction
设置为true
或其他 properties/options)以更快地驱逐它们 - 我鼓励您查看 类似的 问题和已记录的答案 here
However, I don't see any code in this project that runs a delete on this table - just a read and an insert.
代码可能不是 运行 DELETE
s,但 table 定义告诉 Cassandra 删除任何大于等于 80 天的内容。 TTL 创建墓碑。
AND default_time_to_live = 6912000
因此,时间序列模型中 TTL 背后的想法是,它们通常按时间戳降序排列。最终发生的事情是,大多数用例往往只关心最近的数据,并且按时间戳的降序导致墓碑最终出现在分区的“底部”,在那里它们很少(如果有的话)被查询。
要创建该效果,您需要创建一个新的 table,其定义如下:
PRIMARY KEY ((foo1, year, month), created_time, foo2)
) WITH CLUSTERING ORDER BY (created_time DESC, foo2 ASC)