在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中,但我可能会弄错。
答案 0 :(得分:1)
主要问题是您在Cassandra上运行的查询类型。 Cassadra数据模型是查询驱动的,表格被重新计算以提供查询。
通过使用定义良好的主键(分区键和clustring键)创建表。 Cassandra不适合全表扫描类型的查询。
现在来询问。
SELECT * FROM my_table WHERE code = 'test';
这里使用的列是clustring列,它是相等搜索列,它应该是Partition Key的一部分。 Clustring键将出现在不同的分区中,因此如果Read一致性级别为1,则可能会给出空的结果。
SELECT * FROM my_table;
Cassandra不适合这种表扫描查询。在这里,它将搜索所有表并获取所有行(查询不良)。
SELECT * FROM my_table
WHERE id = 'my_id' AND some_text = 'whatever' AND code = 'test';
在这里你提到了一切,所以返回了正确的结果。
答案 1 :(得分:0)
我打开了一个Jira问题,问题已在2.1.18和2.2.10修复: https://issues.apache.org/jira/browse/CASSANDRA-13412
我只是从我在Jira问题中读到的内容发言。修复程序实现后,我没有再次测试上面的场景,因为那时我已经转移到了3.0版本。
最后虽然我最终删除了我的应用程序中几乎所有二级索引的使用,因为我了解到它们导致了糟糕的性能。
原因是在大多数情况下,它们会导致扇出查询,这些查询将联系群集的每个节点,并带来相应的成本。
仍有一些情况下,他们可以表现良好,例如当您通过分区键同时查询时,因为不会涉及其他节点。
但是对于其他任何事情,我的建议是:考虑是否可以删除辅助索引并在辅助表中进行查找。您将负担维护表同步的负担,但性能应该更好。