对于数据模型,如:
create type city (
name text,
code int
);
create table user (
id uuid,
name text,
cities list<FROZEN<city>>,
primary key ( id )
);
create index user_city_index on user(cities);
查询为
select id, cities from user where cities contains {name:'My City', code: 10};
工作正常。但是可以查询
select id, cities from user where cities contains {name:'My City'};
并弃掉code
属性,即code=<any>
?
这可以通过使用Spark来实现吗?
答案 0 :(得分:4)
但是可以查询:
select id, cities from user where cities contains {name:'My City'};
不,不是。 using a UDT个州的文档(对于UDT列name
):
- 过滤用户定义类型列的数据。创建索引,然后运行条件查询。在Cassandra 2.1.x中,您需要列出
醇>name
子句中WHERE
列的所有组件。
因此,查询cities
UDT集合将需要city
类型的所有组件。
我确信有一种方法可以在Spark中查询,但我会给你一个基于Cassandra的答案。基本上,创建一个定义/索引的附加列表列只是为了保存城市名称列表,并在其上运行CONTAINS
。更好的方法是将city
类型反规范化为查询表(usersbycity
),使用PRIMARY KEY定义,如PRIMARY KEY(cityname, citycode, userid)
,并使用除user
表之外的那个按城市名称和代码(或城市名称)支持查询。
请记住,当表格专门设计为适合您的查询模式时,Cassandra效果最佳。二级索引是为了方便,而不是性能。尝试扩充一个表以支持多个查询是RDBMs数据建模方法(通常在Cassandra中不能很好地工作)。而不是一个表可以很好地为一个查询提供服务,通常最终只有一个表可以很好地处理多个查询。
编辑您的问题:
1)“拥有长群集密钥是否可以接受?”
目前我无法找到关于此的明确声明,但我认为这里更大的问题是如何在“引擎盖下”存储/使用群集密钥。实质上,每个聚类键值都附加到每个列值(以便更快地检索)。显然,如果你有很多这样的东西,那就会占用磁盘空间(这些日子并没有太大的担忧......如果是的话,你可以使用COMPACT STORAGE
指令来解决这个问题。)
如果你有很多,最终可能会影响性能。我可以仔细检查这个,然后再回复你。我不会去...说...... 100个聚类键。但我不认为10是一个大问题。我知道我用7或8创建了模型,它们表现得很好。
2)“如果存在与用户相关的其他非规范化表(如usersbyhobby,usersbybookread等),如何将来自这些表的过滤组合到来自userbycity的过滤器到一个查询中,因为c *中没有JOIN?”
您无法在查询时将它们组合在一起。您可以做的是,如果您发现您的查询需要同时来自usersbyhobby,usersbybookread和usersbycity的用户数据;是创建一个包含所有数据的非规范化表。根据您的查询需求,您可能需要以不同的方式订购PRIMARY KEY,在这种情况下,您需要创建与要提供特定查询的表一样多的表。
另一种选择是进行单独查询并在客户端管理它们。客户端JOIN被认为是Cassandra反模式,所以我会谨慎使用它。这完全取决于您的应用程序的需求,以及您是否希望将大部分时间用于数据建模/管理或客户端处理。老实说,我更愿意让客户端保持尽可能简单。