2

在我的应用程序中,我需要对文档进行类似 SQL 的查询。大图是有一个带有分页表的页面,显示了某种“类型”的 couchdb 文档。我有大约 15 个可搜索的列,例如时间戳、客户名称、美国状态、不同的数字字段等。所有这些列都是可排序的,还有一个过滤器表单允许用户按每个字段进行过滤。

下面更具体的是一个典型的查询,它是客户设置一些过滤器选项并进入第二页的结果。它用pseodo-sql代码编写,只是为了解释问题:

timestamp > last_weeks_monday_epoch AND timestamp < this_weeks_monday_epoch AND marked_as_test = False AND dataspace="production" AND fico > 650 SORT BY timestamp DESC LIMIT 15 SKIP 15

如果我使用任何类似 sql 的数据库,这将是一个微不足道的问题,但 couchdb 更有趣;)为了解决这个问题,我创建了一个具有以下发射行结构的视图:

key: [field, value], id: doc._id, value: null

现在,要解决上面的示例查询,我需要执行一堆查询:

  • {startkey: ["timestamp", last_weeks_monday_epoch], endkey: ["timestamp", this_weeks_monday_epoch]}*_epoch这里是整数纪元时间戳,

  • {key: ["marked_as_test", False]},

  • {key: ["dataspace", "production"]},

  • {startkey: ["fico", 650], endkey: ["fico", {}]}

一旦获得上述查询的结果,我就会计算文档 ID 集的交集,并使用时间戳查询的结果应用排序。最后,我可以应用切片解析第 15-30 行的文档 ID,并使用批量获取操作下载它们的内容。

不用说,它不是最快的操作。目前我正在使用的数据集大约有 10K 个文档。我已经可以看到计算集合交集的部分可能需要 4 秒,显然我需要进一步优化它。我不敢想,当我的数据集翻倍、三倍等时,几个月后它会变得多慢。

好的,在解释了我所处的情况之后,让我问一些实际的问题。

  1. 有没有更好、更自然的方法可以在不失去工具灵活性的情况下实现我的目标?

  2. 我使用的视图结构是最优的吗?在某些时候,我正在考虑使用单独的 map() 函数来生成每个字段的值。这将导致 b 树更小,但视图服务器生成索引的工作量更大。我可以这样受益吗?

  3. 我必须计算大集合的交集以便稍后获得结果切片的算法部分困扰着我。它不是一种可扩展的方法。有谁知道更好的算法吗?

4

2 回答 2

1

我不认为 CouchDB 非常适合您的问题的一般解决方案。但是,有两种基本方法可以缓解 CouchDB 解决问题的方式。

  1. 编写/生成一堆map()函数,使用每个单独的列作为键(为了更好的读取/查询性能,您甚至可以使用组合方法)。这样你就可以进行智能过滤和排序,在数据上使用一堆不同的索引。另一方面,这将花费额外的磁盘空间和索引缓存性能。

  2. 尝试找出您的用户实际使用的过滤器/排序顺序,并针对这些进行优化。过滤器/排序顺序的每种组合似乎不太可能被平等地使用,因此您应该能够找到一些最常用的模式并编写最适合这些模式的视图函数。

我更喜欢第二种选择,但这实际上取决于您的用例。这是 SQL 引擎传统上非常擅长的事情之一。

于 2013-08-20T09:15:54.910 回答
1

具有地图功能:

function(doc){
    if(doc.marked_as_test) return;
    emit([doc.dataspace, doc.timestamp, doc.fico], null):
}

您可以提出类似的要求:

 http://localhost:5984/db/_design/ddoc/_view/view?startkey=["production", :this_weeks_monday_epoch]&endkey=["production", :last_weeks_monday_epoch, 650]&descending=true&limit=15&skip=15

但是,您应该从客户端传递:this_weeks_monday_epoch:last_weeks_monday_epoch值(我相信它们是数据库端的一些可计算变量,对吗?)

如果您不关心dataspace字段(例如,它始终是常量),您可以将其移动到地图函数代码中,而不是将其放在查询参数中。

于 2013-08-19T09:57:37.570 回答