如何检查Cassandra表是否存在

23

有没有一种简单的方法可以使用CQL (或API,如com.datastax.driver)来检查是否定义了Cassandra中的表(列族)?

目前,我倾向于执行SELECT 1 FROM table并检查异常,但也许有更好的方法吗?

4个回答

26

从1.1版本开始,您应该能够查询system键空间中的schema_columnfamilies列族。如果您知道要检查哪个键空间,此CQL应列出键空间中的所有列族:

截止到1.1版本,你应该可以查询system keyspace,schema_columnfamilies 列族。如果你已经知道要查询的keyspace,以下CQL将列出该keyspace下所有的列族:

SELECT columnfamily_name
FROM schema_columnfamilies WHERE keyspace_name='myKeyspaceName';

这个功能的描述报告在此处:https://issues.apache.org/jira/browse/CASSANDRA-2477

但是请注意,系统列名称在1.1和1.2之间发生了一些变化。因此,您可能需要稍微调整一下才能获得所需的结果。

编辑20160523 - Cassandra 3.x更新:

请注意,对于Cassandra 3.0及以上版本,您需要对上述查询进行一些调整:

SELECT table_name 
FROM system_schema.tables WHERE keyspace_name='myKeyspaceName';

1
它适用于CQL 3,但不适用于CQL 1或2: SELECT columnfamily_name FROM System.schema_columnfamilies WHERE keyspace_name='myKeyspaceName'; - Datageek
如果有人检查表是否存在,如果不存在则创建它,那么这种方法不是线程安全的。如果多个线程/客户端同时执行此类操作,则SELECT可能会返回无结果,但CREATE语句可能已经失败。在这种情况下,最好采用基于异常的解决方案。 - Wacław Borowiec
它将无法与Datastax v3.0驱动程序一起使用。请使用KeyspaceMetadata/TableMetadata。 - Neil Stockton
@Aaron,有没有一种方法(通过查询系统表)可以在不指定键空间名称的情况下知道表的存在? - Laxmikant
@Laxmikant 是的,如果您知道表名,可以尝试:SELECT * FROM system_schema.tables WHERE table_name='testmap' ALLOW FILTERING; 因为 system_schema 键空间使用了 LocalStrategy,所以与在常规表上使用 ALLOW FILTERING 相比,它不会那么低效。 - Aaron

23

Java驱动程序(因为你在问题中提到了它)也维护着模式的本地表示。

3.x及以下版本的驱动程序:

KeyspaceMetadata ks = cluster.getMetadata().getKeyspace("myKeyspace");
TableMetadata table = ks.getTable("myTable");
boolean tableExists = (table != null);

驱动程序 4.x 及以上版本:

Metadata metadata = session.getMetadata();
boolean tableExists =
  metadata.getKeyspace("myKeyspace")
    .flatMap(ks -> ks.getTable("myTable"))
    .isPresent();

好答案!我甚至没有想到可以使用TableMetadata来做到这一点。 - Aaron
完美!这样你甚至可以轻松访问列定义。 - luk2302
非常适用于DataStax驱动程序v3,感谢Olivier! - albogdano
1
我的问题与C++驱动程序有关,因为在我的情况下,每次传输250Kb的数据。我的当前实现在启动时只获取一次元数据,这大大提高了速度,但数据位于单独的服务中(我有一种代理形式来访问Cassandra)。所以我认为这是最好的方法(最干净的方法),只是它真的很慢。 - Alexis Wilke
使用驱动程序v4需要额外的.get()来解开Optional<KeyspaceMetadata>,但除此之外它仍然可以工作。 - lapo

6

我只需要使用cqlsh手动检查表的存在性。以下是一些可能有用的一般信息。

describe keyspace_name.table_name

如果不存在,您将得到“keyspace中未找到'table_name'”的错误提示。 如果存在,则会返回该表的描述。

0
对于.NET驱动程序CassandraCSharpDriver版本3.17.1,以下代码将在表不存在时创建它:
var ks = _cassandraSession.Cluster.Metadata.GetKeyspace(keyspaceName);
var tableNames = ks.GetTablesNames();
if(!tableNames.Contains(tableName.ToLowerInvariant()))
{
   var stmt = new SimpleStatement($"CREATE TABLE {tableName} (id text PRIMARY KEY, name text, price decimal, volume int, time timestamp)");
   _cassandraSession.Execute(stmt);
}

您需要根据自己的需求调整表列列表。这也可以在异步方法中使用await _cassandraSession.ExecuteAsync(stmt).ConfigureAwait(false)来等待。

另外,我想提一下,我正在使用Cassandra 4.0.1版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接