【发布时间】:2014-10-16 03:05:01
【问题描述】:
我正在运行 Cassandra 集群
Software version: 2.0.9
Nodes: 3
Replication factor: 2
我有一个非常简单的表格,我可以在其中插入和更新数据。
CREATE TABLE link_list (
url text,
visited boolean,
PRIMARY KEY ((url))
);
行没有过期,我没有执行任何删除操作。一旦我运行我的应用程序,由于墓碑单元数量的增加,它很快就会变慢:
Read 3 live and 535 tombstoned cells
它在几分钟内达到数千。
我的问题是,如果我不进行任何删除,是什么负责生成这些单元格?
// 更新
这是我用来通过 com.datastax.driver 与 Cassandra 对话的实现。
public class LinkListDAOCassandra implements DAO {
public void save(Link link) {
save(new VisitedLink(link.getUrl(), false));
}
@Override
public void save(Model model) {
save((Link) model);
}
public void update(VisitedLink link) {
String cql = "UPDATE link_list SET visited = ? WHERE url = ?";
Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getVisited(), link.getUrl());
}
public void save(VisitedLink link) {
String cql = "SELECT url FROM link_list_inserted WHERE url = ?";
if(Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getUrl()).all().size() == 0) {
cql = "INSERT INTO link_list_inserted (url) VALUES (?)";
Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getUrl());
cql = "INSERT INTO link_list (url, visited) VALUES (?,?)";
Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getUrl(), link.getVisited());
}
}
public VisitedLink getByUrl(String url) {
String cql = "SELECT * FROM link_list WHERE url = ?";
for(Row row : Cassandra.DB.execute(cql, url)) {
return new VisitedLink(row.getString("url"), row.getBool("visited"));
}
return null;
}
public List<Link> getLinks(int limit) {
List<Link> links = new ArrayList();
ResultSet results;
String cql = "SELECT * FROM link_list WHERE visited = False LIMIT ?";
for(Row row : Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, limit)) {
try {
links.add(new Link(new URL(row.getString("url"))));
}
catch(MalformedURLException e) { }
}
return links;
}
}
这是执行实现
public ResultSet execute(String cql, ConsistencyLevel cl, Object... values) {
PreparedStatement statement = getSession().prepare( cql ).setConsistencyLevel(cl);
BoundStatement boundStatement = new BoundStatement( statement );
boundStatement.bind(values);
return session.execute(boundStatement);
}
// 更新 2
cfstats 的一个有趣发现表明,只有一张表有墓碑。这是link_list_visited。这是否意味着使用二级索引更新列会创建墓碑?
Table (index): link_list.link_list_visited
SSTable count: 2
Space used (live), bytes: 5055920
Space used (total), bytes: 5055991
SSTable Compression Ratio: 0.3491883995187955
Number of keys (estimate): 256
Memtable cell count: 15799
Memtable data size, bytes: 1771427
Memtable switch count: 1
Local read count: 85703
Local read latency: 2.805 ms
Local write count: 484690
Local write latency: 0.028 ms
Pending tasks: 0
Bloom filter false positives: 0
Bloom filter false ratio: 0.00000
Bloom filter space used, bytes: 32
Compacted partition minimum bytes: 8240
Compacted partition maximum bytes: 7007506
Compacted partition mean bytes: 3703162
Average live cells per slice (last five minutes): 3.0
Average tombstones per slice (last five minutes): 674.0
【问题讨论】:
-
你用的是什么客户端?贴出你用来插入数据的代码……如果你用 cqlsh 来放数据,这会发生吗?
-
com.datastax.driver - 我将代码添加到描述中。
-
我想到的唯一一件事是该表是使用默认 ttl 创建的...您可以打印一个描述表输出吗?如果您使用 cqlsh 放置数据,它们会消失吗?
-
请看我的第二次更新。看起来用二级索引更新列会生成墓碑。不知道有什么办法可以解决它。
-
是的,我用二级索引更新了很多列。每条记录都以“visited = False”开头,目的是让它们都变成“visited = True”。我得出的结论是我以不正确的方式使用 cassandra。我知道不鼓励排队,但我认为如果我不运行删除,就可以摆脱它。