在尝试为我的应用程序实现一些计数器时,我遇到了这种奇怪的行为。 基本上,我做了一个像这样的柜台表:
CREATE TABLE stats_dev.log_counters (
date text PRIMARY KEY,
all counter
);
然后我有一些我想要计算的特定类型的消息,所以在我的Go应用程序中,我改变了表格以添加我之前没有的列。
我的应用程序正在增长,我开始拥有超过30列(不应该超过50个),当我想要检索所有这些计数器时,结果中缺少某些列。
query := s.Query(`SELECT * FROM `+_apiCountersTable+` WHERE date IN ?`, dates)
res, err := query.Iter().SliceMap()
这会让我返回34个超过34列的内容。虽然,当我在CQLSH上做请求时:
cqlsh:stats_dev> SELECT * FROM api_counters WHERE date = 'total';
我得到了正确的完整结果。所以:
我的临时解决方案是从system.schema_columns
表中选择列名,并将SELECT.Join()全部选择到SELECT查询......
非常感谢你的帮助。
答案 0 :(得分:2)
我不熟悉gocql库,但听起来你可能会遇到不重复你的陈述和CASSANDRA-7910的组合。
每当一个请求准备就绪(就像在___中的日期在_中所做的那样?),它会向cassandra发送一个请求,该请求会响应该表的列元数据,所以当你得到一个响应时从cassandra回询,你知道哪些列可供查找。看起来gocql有一个名为Automatic query preparation
的功能,它可能会将您的请求视为准备好的声明。
当你改变一个表时,准备好的语句不会在你的客户端得到更新,所以解决这个问题的唯一方法就是重新编写你的语句(不确定你是否具有gocql的控制级别)。然而,由于cassandra(CASSANDRA-7910)中存在一个错误,因为它本身在其旁边缓存准备好的语句并且没有使其无效,因此仍然无法正常工作。架构发生变化时这个问题在2.1.3(即将推出)中得到修复,可能值得在git中对cassandra-2.1分支进行尝试,看看是否可以解决您的问题。
在应用程序运行时,改变模式不是一种异常模式,所以这是一个应该有效的方案,但遗憾的是并非如此。我看看是否有办法在gocql中重新表示语句。
我看到cluster.go中有一个stmtsLRU
var。如果你能以某种方式达到目的,那么你可以使准备好的陈述无效。如果没有办法做到这一点,最好打开一个针对gocql的问题,因为你可以在其他驱动程序中重新表示语句。我知道java驱动程序允许你这样做,但会给你一个警告。我想这可能是gocql和其他驱动程序之间的一个很大区别,因为在其他驱动程序中你明确使用了一个预处理语句对象,在gocql中它会在库中自动处理。
由于cassandra bug出色,我认为您应该坚持不使用预准备语句,而是进行如下查询:SELECT * FROM api_counters WHERE date = 'total';
答案 1 :(得分:2)
感谢Andy的帮助。
起初,我认为考虑到你告诉我的内容,我宁愿偶尔在SELCT column_name
上做system.schema_columns
并在我改变我的桌子时刷新它。我只会strings.join()
SELECT FROM api_counters
中的列。它工作但是如果我有2个不同的实例,一个会更新架构而另一个会收到GET请求,那么这个也不会知道新列。
然后我重新安排了我的想法并发现显然还有另一种方法可以做到这一点,我只是改变了这个架构:
CREATE TABLE stats_dev.api_counters (
date text,
description text,
all counter,
PRIMARY KEY (date, description)
);
我根据我期待的描述更新字段。到目前为止一切都很好。
我知道这绝对是选项3:我的模式不是最好的。