cassandra 无法执行此查询,因为它可能涉及数据筛选,从而可能导致不可预测的性能

zfciruhq  于 2023-03-12  发布在  Cassandra
关注(0)|答案(3)|浏览(321)

执行existsByEmail方法时出现此错误:Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING
表格:

CREATE TABLE user(id UUID, email varchar, first_name varchar, last_name varchar, PRIMARY KEY (id, email));

Java Spring代码:

@Repository
public interface UserRepository extends CassandraRepository<User, UUID> {
  boolean existsByEmail(String email);
}

@Table
@Data
public class User {

  @PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED, ordinal = 0)
  private UUID id;

  @PrimaryKeyColumn(ordinal = 1)
  private String email;

  @Column("first_name")
  private String firstName;

  @Column("last_name")
  private String lastName;
}

请告诉我原因和解决方法。非常感谢

uyhoqukh

uyhoqukh1#

出现此错误是因为基础请求未使用分区键(id)。
在您的例子中,email是一个集群列(因为如果没有显式提供,它是默认的PrimaryKeyColumn
对于您提供的bean,唯一有效的查询是

select * from user where id=?
select * from user where id=? AND email>?
select * from user where id=? AND email<?
select * from user where id=? AND email=?

"为什么"
根据分区关键字的值对数据进行分区,以便在单个节点上访问所需的所有数据。您可以将要一起检索的数据分组在一起。将列定义为“已分区”列后,它将成为所有查询中的必需列。
使用Apache Cassandra,数据建模策略是基于查询创建表。(如果您需要通过多个请求访问相同的数据,以复制多个表中的数据,这是性能的折衷。

ego6inou

ego6inou2#

为什么
因为电子邮件是主键的第二个(群集)部分。在Cassandra Store中搜索它的性能很差。这正是警告所说的。
它解决方案
如果性能不是您的应用程序的问题(比如少于百万的电子邮件),那么您可以尝试允许过滤。
否则考虑改变你的模型。我建议去掉id,把email作为唯一的主键(和分区的)。

tf7tbtn2

tf7tbtn23#

Mar-Z给出了一个关于改变数据模型的很好的建议。id多久查询一次user表?这是你经常容易访问的吗?如果不是,像这样重新键入表会有所帮助:

CREATE TABLE user (
  id UUID, email varchar, first_name varchar, last_name varchar,
  PRIMARY KEY (email, id));

如果您确实有需要id的查询,最佳实践是构建一个新查询来支持新查询。如果您不介意保持所有数据同步,则可以完全复制该表。或者,您可以仅使用它来引用user表的id,从而有效地使该表成为“手动索引”,如下所示:

CREATE TABLE user_by_email (
  id UUID, email varchar,
  PRIMARY KEY (email));

编辑

如果我想搜索用户的名字,姓氏,地址?
首先,“搜索”和“查询”是有区别的。搜索是提供非常自由的关键词,并期望得到一个大的结果集;查询是提供精确的条件,并期望得到一个特定的、通常很小的结果集。
记住这一点,您将需要确保主键定义与查询条件匹配,并按重要性降序排列。对于本例,按名字查询并不是非常有价值,因为常见的名字不会导致任何特定的内容。支持名称查询的表如下所示:

CREATE TABLE user_by_name (
  id UUID, email varchar, first_name varchar, last_name varchar,
  PRIMARY KEY (last_name, first_name, id));

基本上,为名称查询构建一个表需要先有last_name,然后是first_nameid以确保唯一性。

相关问题