我正在尝试将RDBMS模型移交给Cassandra,并且很难创建模式。这是我的数据模型:
CREATE TABLE Domain (
ID INT NOT NULL PRIMARY KEY,
DomainName NVARCHAR(74) NOT NULL,
HasBadWords BIT,
...
);
INSERT INTO Domain (DomainName, HasBadWords) VALUES ('domain1.com', 0);
INSERT INTO Domain (DomainName, HasBadWords) VALUES ('domain2.com', 0);
CREATE TABLE ZoneFile (
ID INT NOT NULL PRIMARY KEY,
DomainID INT NOT NULL,
Available BIT NOT NULL,
Nameservers NVARCHAR(MAX),
Timestamp DATETIME NOT NULL
);
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (1, 0, "ns1", '2010-01-01');
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (2, 0, "ns1", '2010-01-01');
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (1, 1, "ns2", '2011-01-01');
INSERT INTO ZoneFile (DomainID, Available, Nameservers, Timestamp) VALUES (2, 1, "ns2", '2011-01-01');
CREATE TABLE Backlinks (
ID INT NOT NULL PRIMARY KEY,
DomainID INT NOT NULL,
Backlinks INT NOT NULL,
Indexed INT NOT NULL,
Timestamp DATETIME NOT NULL
);
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (1, 100, 200, '2010-01-01');
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (2, 300, 600, '2010-01-01');
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (1, 500, 1000, '2010-01-01');
INSERT INTO Backlinks (DomainID, Backlinks, Indexed, Timestamp) VALUES (2, 600, 1200, '2010-01-01');
由此,我推断出我可能有一个Keyspace:DomainData。在这个密钥空间中,我可以有一个名为“Domain”的列家族,就像我在sql中的Domain表一样:
"Domain" : { //ColumnFamily
"domain1.com" : { "HasBadWords" : 0 }, //SuperColumn
"domain2.com" : { "HasBadWords" : 0 } //SuperColumn
}
接下来的表格让我感到困惑。 ZoneFile和Backlinks本质上应该存储查找每个域的这些值的结果历史记录。因此,一个域到多个ZoneFile记录。出于查询目的,我希望能够轻松获得“最新”的ZoneFile记录或给定的域。我需要对Backlinks做同样的事情。
我正在考虑这样的事情,并对域的密钥进行范围查找,然后获取应该是最新时间戳的“最后”记录...
"ZoneFiles" : { //ColumnFamily
"domain1.com:2010-01-01 12:00:00.000" : { "Available" : 0, "Nameservers" : "ns1" }, //SuperColumn
"domain1.com:2011-01-01 12:00:00.000" : { "Available" : 1, "Nameservers" : "ns2" }, //SuperColumn
"domain2.com:2010-01-01 12:00:00.000" : { "Available" : 0, "Nameservers" : "ns1" }, //SuperColumn
"domain2.com:2011-01-01 12:00:00.000" : { "Available" : 1, "Nameservers" : "ns2" } //SuperColumn
}
我不相信这是正确的答案,键中字符串域和字符串日期时间的组合感觉不对。有人能指出我正确的方向吗?
修改
假设我使用:
"ZoneFiles" : {
"domain1.com" : {
timestamp1 : "{\"available\":1,\"nameservers\":\"ns1\"}",
timestamp2 : "{\"available\":1,\"nameservers\":\"ns1\"}",
}
}
如何查询最新时间戳早于给定日期的域行列表?
答案 0 :(得分:4)
如果我正确理解您的问题,您想要对此模型进行的唯一查询是“请为我提供给定域名的最新区域文件或反向链接”?
如果是这种情况,我会在域“行”键下的“域”列系列中将这些值的最新值存储在单独的列中。我还会在更新此最新值时存储(时间戳)。每次在zonefile和反向链接中获取信息的新值时,我只会覆盖“域”列族中的值并更新时间戳。
我假设您也保留了这些历史数据,以便您可以查询它,并且我假设查询类型将“在两次之间向我显示给定域的所有更新”(这是正确的吗?)。如果是这样,我不会手动构造这样的复合行键,因为它将要求您使用Order Preserving Partitioner从get_range_slices获取正确的结果。正如您可能知道的那样,使用OPP进行负载平衡可能是一项艰巨的任务。
相反,我会将行键设为域ID,列键是更新的时间戳。然后,您可以将更新打包到单个值(例如,使用json),使用超级列或使用0.8中的新复合键。如果像这样完成,您可以使用get_slice来满足您的查询,并且它将与Random Partitioner一起正常运行,从而使负载平衡变得更加容易。
汤姆威尔基| Acunu | www.acunu.com | @tom_wilkie回复评论:“我如何查询最近的zonefile时间戳列早于给定时间戳的域列表?”
您可以通过插入另一个列系列来实现:
row key: day (or hour, or some other reasonable 'bucketing')
column key: timestamp of update
value: domain
...每次更新zonefile时。然后,要从t获取最近更新的域,请执行:
result = []
for i in day(t) ... day(now):
result.extend(get_slice(i, range(t, '')))
这将要求您从结果中删除重复条目,因此只有在t很近时才会起作用。您还必须考虑写入的负载平衡,这会将所有负载集中在单个服务器上(因为,在任何时候,您只插入一行)
如果这些权衡不合适,那么您可以查看hadoop集成并使用它来执行此查询。或者您可以进行其他权衡(使用OPP,或者在写入之前执行读取以删除重复项,这将是v。慢)