没有分区键的 Cassandra 查询 table
Cassandra query table without partition key
作为迁移作业的一部分,我正在尝试从 table 中提取数据。
架构如下:
CREATE TABLE IF NOT EXISTS ${keyspace}.entries (
username text,
entry_type int,
entry_id text,
PRIMARY KEY ((username, entry_type), entry_id)
);
为了查询table我们需要分区键,主键的第一部分。
因此,如果我们知道 username
和 entry_type
,我们可以查询 table.
在这种情况下,username
可以是任何值,但 entry_type
是 0-9 范围内的整数。
在进行提取时,我们为每个用户名迭代 table 10 次,以确保我们尝试所有版本的 entry_type
。
我们无法再找到任何条目,因为我们已经耗尽了我们的用户名列表。但是我们的 nodetool tablestats
报告 table 中仍有数据,甚至有千兆字节。因此我们假设 table 不为空。
但我无法找到一种方法来检查 table 以找出 table 中保留的用户名。如果我可以检查它,我可以将留在 table 中的用户名添加到我们的提取作业中,最终我们可以耗尽 table。但我不能简单地查询 table 这样的:
SELECT * FROM ${keyspace}.entries LIMIT 1
因为 cassandra 需要分区键才能进行有意义的查询。
我怎样才能弄清楚我们的 table 中还剩下什么?
根据评论,迁移过程包括来自 Cassandra 的 DELETE 操作 table,但引擎在实际从磁盘中删除受影响的记录之前会有延迟;这个过程由墓碑和 table 的 gc_grace_seconds
属性在内部控制。这个延迟的原因在这个blog entry中有充分的解释,对于一个tl dr,如果默认值仍然存在,Cassandra从执行删除之前至少需要经过10天(864,000秒)实际删除数据。
对于您的情况,一种处理方法是:
- 确保您所有的节点都是 "Up" 和 "Healthy" (
UN
)
减少你的table的gc_grace_seconds属性,在例子中,它会设置为1分钟,而默认是
ALTER TABLE .entries with GC_GRACE_SECONDS = 60;
手动压缩table:
nodetool 压缩条目
该过程完成后,nodetool tablestats
应该是最新的
为了回答您的第一个问题,我想对 gc_grace_seconds 属性 进行更多阐述。
在 Cassandra 中,数据的删除方式与 RDBMS 中的不同。 Cassandra 专为高写入吞吐量而设计,并避免先读后写。所以在 Cassandra 中,删除实际上是更新,而更新实际上是插入。写入 “逻辑删除” 标记以指示数据现在(逻辑上)被删除(也称为软删除)。必须删除标记为逻辑删除的记录才能收回存储 space。这是由一个名为 Compaction 的过程完成的。但请记住,仅在称为 gc_grace_seconds 的特定秒数后,墓碑才有资格进行物理删除/垃圾收集。这是一个非常好的博客,可以详细阅读:https://thelastpickle.com/blog/2016/07/27/about-deletes-and-tombstones.html
现在您可能正在查看 gc_grace_seconds 之前的 table 大小,并且数据仍然存在。
关于您的第二个问题,您希望在不提供分区键的情况下从 table 中获取一些样本。您可以使用 Spark 分析您的 table 内容。 Spark Cassandra Connector 允许您创建 Java 使用 Spark 分析数据库数据的应用程序。您可以按照文章/文档编写一个快速方便的 spark 应用程序来分析 Cassandra 数据。
https://docs.datastax.com/en/dse/6.0/dse-dev/datastax_enterprise/spark/sparkJavaApi.html
我建议您在迁移时不要删除记录。而是首先完成迁移,然后 post 进行快速验证/验证以确保所有记录都成功迁移(这种使用可以轻松地使用 Spark 购买比较来自新旧 table 的数据帧)。 Post 成功验证截断旧的 table,因为截断不会创建墓碑,因此效率更高。请注意,大量的墓碑不利于集群健康。
作为迁移作业的一部分,我正在尝试从 table 中提取数据。
架构如下:
CREATE TABLE IF NOT EXISTS ${keyspace}.entries (
username text,
entry_type int,
entry_id text,
PRIMARY KEY ((username, entry_type), entry_id)
);
为了查询table我们需要分区键,主键的第一部分。
因此,如果我们知道 username
和 entry_type
,我们可以查询 table.
在这种情况下,username
可以是任何值,但 entry_type
是 0-9 范围内的整数。
在进行提取时,我们为每个用户名迭代 table 10 次,以确保我们尝试所有版本的 entry_type
。
我们无法再找到任何条目,因为我们已经耗尽了我们的用户名列表。但是我们的 nodetool tablestats
报告 table 中仍有数据,甚至有千兆字节。因此我们假设 table 不为空。
但我无法找到一种方法来检查 table 以找出 table 中保留的用户名。如果我可以检查它,我可以将留在 table 中的用户名添加到我们的提取作业中,最终我们可以耗尽 table。但我不能简单地查询 table 这样的:
SELECT * FROM ${keyspace}.entries LIMIT 1
因为 cassandra 需要分区键才能进行有意义的查询。
我怎样才能弄清楚我们的 table 中还剩下什么?
根据评论,迁移过程包括来自 Cassandra 的 DELETE 操作 table,但引擎在实际从磁盘中删除受影响的记录之前会有延迟;这个过程由墓碑和 table 的 gc_grace_seconds
属性在内部控制。这个延迟的原因在这个blog entry中有充分的解释,对于一个tl dr,如果默认值仍然存在,Cassandra从执行删除之前至少需要经过10天(864,000秒)实际删除数据。
对于您的情况,一种处理方法是:
- 确保您所有的节点都是 "Up" 和 "Healthy" (
UN
) 减少你的table的gc_grace_seconds属性,在例子中,它会设置为1分钟,而默认是
ALTER TABLE .entries with GC_GRACE_SECONDS = 60;
手动压缩table:
nodetool 压缩条目
该过程完成后,
nodetool tablestats
应该是最新的
为了回答您的第一个问题,我想对 gc_grace_seconds 属性 进行更多阐述。
在 Cassandra 中,数据的删除方式与 RDBMS 中的不同。 Cassandra 专为高写入吞吐量而设计,并避免先读后写。所以在 Cassandra 中,删除实际上是更新,而更新实际上是插入。写入 “逻辑删除” 标记以指示数据现在(逻辑上)被删除(也称为软删除)。必须删除标记为逻辑删除的记录才能收回存储 space。这是由一个名为 Compaction 的过程完成的。但请记住,仅在称为 gc_grace_seconds 的特定秒数后,墓碑才有资格进行物理删除/垃圾收集。这是一个非常好的博客,可以详细阅读:https://thelastpickle.com/blog/2016/07/27/about-deletes-and-tombstones.html
现在您可能正在查看 gc_grace_seconds 之前的 table 大小,并且数据仍然存在。
关于您的第二个问题,您希望在不提供分区键的情况下从 table 中获取一些样本。您可以使用 Spark 分析您的 table 内容。 Spark Cassandra Connector 允许您创建 Java 使用 Spark 分析数据库数据的应用程序。您可以按照文章/文档编写一个快速方便的 spark 应用程序来分析 Cassandra 数据。
https://docs.datastax.com/en/dse/6.0/dse-dev/datastax_enterprise/spark/sparkJavaApi.html
我建议您在迁移时不要删除记录。而是首先完成迁移,然后 post 进行快速验证/验证以确保所有记录都成功迁移(这种使用可以轻松地使用 Spark 购买比较来自新旧 table 的数据帧)。 Post 成功验证截断旧的 table,因为截断不会创建墓碑,因此效率更高。请注意,大量的墓碑不利于集群健康。