在主键上执行两次查找或在非主键上执行一次查找是否更快?

时间:2017-11-13 08:08:53

标签: sql database cassandra cql cql3

我正在用cassandra为用户创建一个表。用户拥有唯一的user_id和唯一的display_name

我的表目前类似于:

create table user (user_id text primary key,
    display_name text,
    joined timestamp,
    last_seen timestamp,
    ...);

当新用户创建帐户时,我需要检查他们输入的显示名称是否已经是别人的。我能做到这一点的最快方法是什么?

这个项目对我来说主要是一个学习项目,我想在半现实世界的情况下尝试一些NoSQL概念。

我自己的想法是使用两个这样的表:

create table user (user_id text primary key,
    display_name text,
    joined timestamp,
    last_seen timestamp,
    ...);

create table user_by_display_name (display_name text primary key, user_id text);

然后在user_by_display_name中查找是否存在用户名将比查找user where display_name = ?更快。这是正确的假设吗?

我觉得主键上的两次查找user_by_display_name where display_name = ?然后使用user_id中的user进行另一次查找可能比单user where display_name = ?次查找慢,如果我需要有关该用户的信息。

1 个答案:

答案 0 :(得分:0)

您的假设是正确的,您将需要按照描述进行非规范化。首先设计查询然后构建表。

你的桌子应该是

CREATE TABLE users (
  user_id text, 
  display_name text,
  last_seen timestamp,
  PRIMARY KEY(user_id)
WITH ...);

CREATE TABLE users_by_display_name (
  display_name text, 
  user_id text, 
  last_seen timestamp,
  PRIMARY KEY(display_name);

这样你就可以进行1次查找。写入便宜,读取费用昂贵。尽可能避免读取。也就是说,您的分区是1行,您在Key值数据库中进行查找。你的第二个选择也不会非常昂贵。

您可以按照描述创建第二个表。根据您正在运行的cassandra版本,您还可以从用户表中创建MATERIALIZED VIEW以实现相同的查找。如果您经常更新last_seen属性,因为他们会在更新行时删除这些内容,因此您不想使用这些内容。所以可能只限于display->userId

一旦进行了查找设置,您仍然需要担心两个用户窃取相同用户名的竞争条件。在这种情况下,您可能会考虑轻量级交易。也就是说,你想避免经常这样做,因为它们很贵。

然而,LWT确实遇到了一些问题,比如他们不是"真的"事务并且它们比标准读/写慢。只要确保你知道自己得到了什么。