1

在 Cassandra 2.2.3 上执行 SELECT 时,我正在处理一个令人费解的行为。我在环中有 4 个节点,我创建了以下键空间、表和索引。

CREATE KEYSPACE IF NOT EXISTS my_keyspace
    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};

CREATE TABLE my_keyspace.my_table (
    id text,
    some_text text,
    code text,
    some_set set<int>,
    a_float float,
    name text,
    type int,
    a_double double,
    another_set set<int>,
    another_float float,
    yet_another_set set<text>,
    PRIMARY KEY (id, some_text, code)
) WITH read_repair_chance = 0.0
   AND dclocal_read_repair_chance = 0.1
   AND gc_grace_seconds = 864000
   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' }
   AND compression = { 'sstable_compression' : 'org.apache.cassandra.io.compress.LZ4Compressor' }
   AND default_time_to_live = 0
   AND speculative_retry = '99.0PERCENTILE'
   AND min_index_interval = 128
   AND max_index_interval = 2048;

CREATE INDEX idx_my_table_code ON my_keyspace.my_table (code);

然后我在表上插入一些行。其中一些有空集。我通过默认的 CQL 客户端执行此查询并获得我期望的行:

SELECT * FROM my_table WHERE code = 'test';

然后我运行了一些我无法控制的测试。我不知道他们做了什么,但我希望他们阅读并可能插入/更新/删除一些行。我确信他们不会删除或更改索引、表或键空间中的任何设置。

测试后,我通过默认的 CQL 客户端再次登录并运行以下查询。

SELECT * FROM my_table WHERE code = 'test';
SELECT * FROM my_table;
SELECT * FROM my_table WHERE id = 'my_id' AND some_text = 'whatever' AND code = 'test';

第一个不返回任何东西。第二个返回所有行,包括 code = 'test' 的行。第三个返回第一个查询无法检索的预期行。

我可以看到这一行与其他行之间的唯一区别是它是包含一些空集的行之一,如前所述。如果我查询另一行也包含一些空集,我会得到相同的行为。

我会说这个问题与二级索引有关。不知何故,在测试期间执行的操作使索引处于看不到某些行的状态。

我显然错过了一些东西。您对可能导致这种行为的原因有任何想法吗?

提前致谢。

更新:

我解决了这个问题,但现在我在其他地方发现了同样的问题。由于问题首次发生,我发现了有关错误之前执行的操作的更多信息:更新为所述列设置 TTL 的特定列。经过一番调查,我发现了一些可能与此问题有关的 Jira 问题:

https://issues.apache.org/jira/browse/CASSANDRA-6782 https://issues.apache.org/jira/browse/CASSANDRA-8206

但是,这些问题似乎已经在 2.0 和 2.1 上得到解决,而我正在使用 2.2。我认为这些更改包含在 2.2 中,但我可能弄错了。

4

2 回答 2

1

主要问题是您在 Cassandra 上运行的查询类型。Cassadra 数据模型是查询驱动的,表被重新计算以服务于查询。

表是使用定义良好的主键(分区键和集群键)创建的。Cassandra 不适合全表扫描类型的查询。

现在来回答您的问题。

  1. SELECT * FROM my_table WHERE code = 'test';

这里使用的列是 clustring 列,它是相等搜索列,它应该是 Partition Key 的一部分。簇键将出现在不同的分区中,因此如果读取一致性级别为 1,它可能会给出空结果。

  1. SELECT * FROM my_table;

Cassandra 不适合这种表扫描查询。在这里它将搜索所有表并获取所有行(查询不佳)。

  1. SELECT * FROM my_table WHERE id = 'my_id' AND some_text = 'whatever' AND code = 'test';

在这里,您提到了所有内容,因此返回了正确的结果。

于 2016-08-08T10:07:48.680 回答
1

我打开了一个 Jira 问题,问题已在 2.1.18 和 2.2.10 上得到解决: https ://issues.apache.org/jira/browse/CASSANDRA-13412

我只是根据我在 Jira 问题中读到的内容发言。修复实施后,我没有再次测试上述场景,因为那时我已经转移到 3.0 版本。

最后,尽管我最终删除了应用程序中几乎所有二级索引的使用,因为我了解到它们会导致性能不佳。

原因是在大多数情况下,它们会导致扇出查询,这些查询将联系集群的每个节点,并产生相应的成本。

在某些情况下它们仍然可以很好地执行,例如当您同时按分区键查询时,因为不会涉及其他节点。

但对于其他任何事情,我的建议是:考虑是否可以删除二级索引并在辅助表中进行查找。您将承担保持表同步的负担,但性能应该会更好。

于 2018-04-03T21:11:08.520 回答