问题描述
我一直在阅读有关 datastax 的 Cassandra Db 文档以及 Apache 文档。到目前为止,我已经了解到我们不能在一张表上创建多个索引(一个主索引,一个二级索引)。每个查询都应该有一个单独的表。 将此与 sql 表进行比较,例如我们要查询 4 个字段的表,对于此表,在 Cassandra 的情况下,我们应该将此表拆分为 4 个表,对吗? (如果我错了,请纠正我)。 在这 4 个表上,我可以拥有索引并进行查询, 我的问题是如何将数据插入到这4张表中,我应该连续发出4次插入请求吗?
我的首要任务是避免二级索引
解决方法
要在非规范化表之间保持数据同步,您需要使用 CQL BATCH
语句。
例如,如果您要维护这些表:
movies
movies_by_actor
movies_by_genre
然后您可以像这样在 CQL BATCH
中对更新进行分组:
BEGIN BATCH
INSERT INTO movies (...) VALUES (...);
INSERT INTO movies_by_actor (...) VALUES (...);
INSERT INTO movies_by_genre (...) VALUES (...);
APPLY BATCH;
请注意,也可以批量执行 UPDATE
和 DELETE
语句以及条件写入。
上面的例子在cqlsh中只是为了说明,实际中并未使用。以下是使用 Java 驱动程序的示例 BatchStatement
:
SimpleStatement insertMovies =
SimpleStatement.newInstance(
"INSERT INTO movies (...) VALUES (?,...)",<some_values>);
SimpleStatement insertMoviesByActor =
SimpleStatement.newInstance(
"INSERT INTO movies_by_actor (...) VALUES (?,<some_values>);
SimpleStatement insertMoviesByGenre =
SimpleStatement.newInstance(
"INSERT INTO movies_by_genre (...) VALUES (?,<some_values>);
BatchStatement batch =
BatchStatement.builder(DefaultBatchType.LOGGED)
.addStatement(insertMovies)
.addStatement(insertMoviesByActor)
.addStatement(insertMoviesByGenre)
.build();
有关详细信息,请参阅 Java driver Batch statements。干杯!
,Cassandra 支持二级索引,SSTable Attached Secondary Index(SASI)。存储附加索引 (SAI) 已捐赠给该项目,但尚未被接受。
您需要创建您的表,以便您可以使用类似这样的单个查询从表中获取所有需要的数据
SELECT * from keyspace.table_name where key = 'ABC';
那么对于设计师来说,这意味着什么。您需要识别所有查询,并根据这些查询定义数据模型(表)。因此,如果您认为需要 4 个表来满足您的查询,那么您是对的。
由于您定义的所有 4 个表如果表示相同的数据,则必须保持同步,因此最好的方法是使用批处理
BEGIN BATCH
DML_statement1 ;
DML_statement2 ;
DML_statement3 ;
DML_statement4 ;
APPLY BATCH ;
Batch 不保证所有语句都会成功回滚。它通知客户端语句组失败。所以客户应该重新尝试应用它们。
如果可以,最好避免使用二级索引,因为它们存在性能问题。一般的经验法则是索引具有少量值的低基数的列。