2015-03-31 61 views
3

我有一个用户模型,其特征如下: -Cassandra-数据建模UserProfilie

class User(Model): 
    user_id = columns.Integer(primary_key=True) 
    username = columns.Text() 
    email = columns.Text() 
    fname = columns.Text() 
    lname = columns.Text() 
    age = columns.Text() 
    state = columns.Text() 
    city = columns.Text() 
    country = columns.Text() 
    gender = columns.Text() 
    phone = columns.Text() 
    school_name = columns.Text() 
    created_at = columns.Text() 
    race = columns.boolean() 

这是我的正常RDBMS模型。我的查询如下: -

1) Get all users with city = 'something' 

2) Get a user with email = 'something' 

3) Get a user with username = 'something' 

4) Get all users with phones IN ('something') 

5) Get all users with state = 'something' 

6) Get all users with age > something 

7) Get all users with gender = 'something' 

8) Get all users with race = 'something' 

9) Get count(*),school_name users Group By schoolname 

10) Get all users with created_date > 'something' LIMIT 1000 

11) Get all users with username IN ('something') AND age IN ('something') AND phone IN ('something') AND state IN ('something') AND so on LIMIT 1000 

我可以得到上述结果与数据库管理系统的一个简单的选择查询的查询,但问题在于卡桑德拉。

因为为了在Cassandra中获得上述查询的结果,建议每个查询都有一个不同的模型,这将加快读取能力。在这个时代,磁盘比以前更便宜。这就是说,我明白,只是抛出更多磁盘来解决问题并不总是容易的。我看到的更大的问题是调整应用程序的DAO层以保持10个不同的表同步。 (另外,我的内心本能并不认为有10个模型适用于不同的查询:P)

可以请某人解释我在卡桑德拉的合适模型以获得这些查询的结果吗?

PS:对上述模型的操作可以是Read/Write/Update/Delete。 查询11是最重要的查询。

考虑到有关特定用户的信息可以更新,最重要的是使这些查询在大量数据上真正快速。

回答

0

您正面临真正的Cassandra限制:如果您确定要与Cassandra一起使用需要遵循“卡桑德拉规则”。这其中有

  • 去正规化
  • 选择指数明智

因此,让我们开始吧。每个用户应该有唯一的ID,用户名,电子邮件和电话。这意味着这些列不适合索引(read here why),所以非规范化是正确的方法。

从您的查询中,您将拥有user_by_username,user_by_email和user_by_phones。您可能认为每次重复数据在更新和磁盘使用方面可能都很麻烦:因此,您可以通过创建每个仅包含用户ID的值作为折衷方案来妥协。即g:

user_email  | user_id 
--------------+------------------- 
[email protected] | 123-456-7aa |  
[email protected] | efg-123-ghi | 

在KS内部的另一个表中,您需要一个表格,通过id将检索关于用户的所有信息。这将解决update problem,如果您需要更新电子邮件地址或手机,则只能更新多个表而不是N个。不好的一面是您必须执行两个查询来获取数据。

让我们继续。

stategenderrace是被索引,原因如下很好的候选人:

  1. 低基数
  2. 许多行会包含这些值

通过索引你将解决一些其他查询。最难的部分是这种类型的查询时,就不会允许卡桑德拉像

select * from users where age > xyz 

查询,因为你需要在丛集部分执行!“等于”操作。要做到这一点,您需要通过某种常用密钥来“组织”用户:如状态或“状态组” - 这意味着要了解具有特定年龄的所有用户,您必须查询每个分区。

小心:我没有提供解决方案,这不是我的目标 - 我试图做的是提供一种方法来解决Cassandra的这个问题。

HTH,
卡罗

+0

感谢@Carlo提供一种可能的方法对上述问题的深度解读。最后一个问题。如果将来,我决定写一个涉及'过滤用户状态'的查询,那么我需要创建另一个列家族? **如我错了请纠正我**。因此,为了创建另一个列族,我需要将其他CF中的数据迁移(复制)到最新的bulit CF中。不是吗? – PythonEnthusiast 2015-04-07 09:56:39

+0

是的,您是对的:如果您需要使用新查询获得过去数据的信息,那么您已经将这些数据迁移到新表中 – 2015-04-07 10:14:48

+0

但是之后它再次成为手动操作,将数亿行数据从CF复制到另一个。由于我无法在一开始就冻结我的所有要求,因此您对此有何看法? – PythonEnthusiast 2015-04-07 10:21:59

1

可能最简单的方法是使用Datastax Enterprise和Search(Solr)或Analytics(Spark)选项。您可以免费从www.datastax.com下载以用于测试目的。只要您的SLA数据可用于查询超过1秒,lucene索引应该能够处理这些不同的搜索选项。

更大的问题是为什么你想在这里使用卡桑德拉?你说的大量数据是什么意思?通常,当您的应用程序具有低延迟读写需求,可以复制到许多服务器和许多数据中心以及没有停机时间时,Cassandra的功能最佳。这在数据集市/仓库或分析数据库中通常不是必需的,通过查询类型和您需要在“大量数据”上执行该操作似乎指出了这一点。每个Cassandra节点通常不会放置超过1 - 3T的数据,尽管这里有一些异常值...