在用户定义类型 (UDT) 列表中使用 "contains" 进行查询
Querying with "contains" on a list of user defined type (UDT)
对于这样的数据模型:
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可以实现吗?
But is it possible to query: select id, cities from user where cities contains {name:'My City'};
不,不是。 using a UDT 上的文档指出(对于 UDT 列 name
):
- Filter data on a column of a user-defined type. Create an index and then run a conditional query. In Cassandra 2.1.x, you need to list all components of the
name
column in the WHERE
clause.
因此查询您的 cities
UDT 集合将需要 city
类型的所有组件。
我确定有一种方法可以在 Spark 中查询这个,但我会给你一个基于 Cassandra 的答案。基本上,创建一个额外的列表列 defined/indexed 只是为了保存城市名称列表,并且 运行 你的 CONTAINS
就在上面。更好的是,将 city
类型非规范化为查询 table (usersbycity
),并使用 PRIMARY KEY(cityname, citycode, userid)
之类的 PRIMARY KEY 定义,并在 [=20] 之外使用它=] table 支持按城市名称和代码(或仅城市名称)进行查询。
请记住,当 table 专为适合您的查询模式而设计时,Cassandra 的性能最佳。二级索引是为了方便,而不是性能。尝试增加一个 table 以支持多个查询是一种 RDBM 数据建模方法(在 Cassandra 中通常效果不佳)。而不是一个 table 很好地服务于一个查询,你通常最终得到一个 table 服务于多个查询很差。
编辑您的问题:
1) "Is it acceptable to have long clustering keys?"
目前我找不到关于此的明确声明,但我认为这里更大的问题在于聚类键是如何 stored/used "under the hood." 本质上,每个聚类键值都附加到每个列值(用于更快的检索)。显然,如果你有很多,那会占用磁盘 space(现在不是什么大问题……如果是的话你可以用 COMPACT STORAGE
指令来解决)。
如果您有很多,最终可能会影响性能。我可以仔细检查一下,然后再给您答复。我不会去……说……100 个集群密钥。但我认为 10 没什么大不了的。我知道我已经使用 7 或 8 创建了模型,并且它们的性能很好。
2) "If there are other denormalized tables (like usersbyhobby, usersbybookread etc.) related to user, how can I combine filtering from these tables to filters from usersbycity into one query, since there is no JOINs in c*?"
您不能在查询时合并它们。您可以做的是,如果您发现有一个查询同时需要来自 usersbyhobby、usersbybookread 和 usersbycity 的数据;是创建一个包含所有这些数据的非规范化 table。根据您的查询需求,您可能需要以不同的方式对 PRIMARY KEY 进行排序,在这种情况下,您需要创建与要服务的特定查询一样多的 table。
另一种选择是进行单独的查询并在客户端进行管理。客户端 JOIN 被认为是 Cassandra 反模式,所以我会谨慎使用它。这完全取决于您的应用程序的需求,以及您是想将大部分时间花在处理数据 modeling/management 还是花在客户端处理上。老实说,我更喜欢让客户端尽可能简单。
对于这样的数据模型:
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可以实现吗?
But is it possible to query:
select id, cities from user where cities contains {name:'My City'};
不,不是。 using a UDT 上的文档指出(对于 UDT 列 name
):
- Filter data on a column of a user-defined type. Create an index and then run a conditional query. In Cassandra 2.1.x, you need to list all components of the
name
column in theWHERE
clause.
因此查询您的 cities
UDT 集合将需要 city
类型的所有组件。
我确定有一种方法可以在 Spark 中查询这个,但我会给你一个基于 Cassandra 的答案。基本上,创建一个额外的列表列 defined/indexed 只是为了保存城市名称列表,并且 运行 你的 CONTAINS
就在上面。更好的是,将 city
类型非规范化为查询 table (usersbycity
),并使用 PRIMARY KEY(cityname, citycode, userid)
之类的 PRIMARY KEY 定义,并在 [=20] 之外使用它=] table 支持按城市名称和代码(或仅城市名称)进行查询。
请记住,当 table 专为适合您的查询模式而设计时,Cassandra 的性能最佳。二级索引是为了方便,而不是性能。尝试增加一个 table 以支持多个查询是一种 RDBM 数据建模方法(在 Cassandra 中通常效果不佳)。而不是一个 table 很好地服务于一个查询,你通常最终得到一个 table 服务于多个查询很差。
编辑您的问题:
1) "Is it acceptable to have long clustering keys?"
目前我找不到关于此的明确声明,但我认为这里更大的问题在于聚类键是如何 stored/used "under the hood." 本质上,每个聚类键值都附加到每个列值(用于更快的检索)。显然,如果你有很多,那会占用磁盘 space(现在不是什么大问题……如果是的话你可以用 COMPACT STORAGE
指令来解决)。
如果您有很多,最终可能会影响性能。我可以仔细检查一下,然后再给您答复。我不会去……说……100 个集群密钥。但我认为 10 没什么大不了的。我知道我已经使用 7 或 8 创建了模型,并且它们的性能很好。
2) "If there are other denormalized tables (like usersbyhobby, usersbybookread etc.) related to user, how can I combine filtering from these tables to filters from usersbycity into one query, since there is no JOINs in c*?"
您不能在查询时合并它们。您可以做的是,如果您发现有一个查询同时需要来自 usersbyhobby、usersbybookread 和 usersbycity 的数据;是创建一个包含所有这些数据的非规范化 table。根据您的查询需求,您可能需要以不同的方式对 PRIMARY KEY 进行排序,在这种情况下,您需要创建与要服务的特定查询一样多的 table。
另一种选择是进行单独的查询并在客户端进行管理。客户端 JOIN 被认为是 Cassandra 反模式,所以我会谨慎使用它。这完全取决于您的应用程序的需求,以及您是想将大部分时间花在处理数据 modeling/management 还是花在客户端处理上。老实说,我更喜欢让客户端尽可能简单。