在关系数据库中高效实现分面搜索

时间:2009-12-04 16:01:23

标签: sql database database-design tagging faceted-search

我正在尝试使用多标记过滤实现Faceted search或标记。在分面导航中,仅显示非空类别,并且在括号中显示类别中也匹配已应用标准的项目数。

I can get all items having assigned categories using INNER JOINsget number of items in all category using COUNT and GROUP BY,但我不确定它将如何扩展到数百万个对象和数千个标签。特别是计数。

我知道有一些非关系型解决方案,比如Lucene + SOLR,但我也发现了一些基于闭源RDBMS的实现,据说这些实现像FacetMap.com或{Endeca或{ {3}}软件,因此必须有一种有效的方法在关系数据库中执行分面搜索。

是否有人有分面搜索的经验并且可以给出一些提示?

缓存每个类别集的计数?也许使用一些智能增量技术来更新计数器?

编辑:

可以在此处找到分面导航的示例:Flamenco

目前我有标准的3表方案(项目,标签和items_tags,如此处所述:http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html#toxi)以及facet表。每个标签都分配了一个方面。

4 个答案:

答案 0 :(得分:5)

IMO,关系数据库并不擅长搜索。您可以通过专用搜索引擎(如Solr / Lucene)获得更好的性能。

答案 1 :(得分:5)

我只能确认尼尔斯说的话。 RDBMS不适合多维搜索。我使用过一些智能解决方案,缓存计数器,使用触发器等等。但最终,外部专用索引器总能获胜。

可能,如果您将数据转换为维度模型并将其提供给某些OLAP [我的意思是MDX引擎] - 它将表现良好。但它似乎有点过于沉重的解决方案,而且肯定不是实时的。

相反,使用专用索引引擎(想想Lucene,想想Sphinx)的解决方案可以通过增量索引更新近乎实时地进行。

答案 2 :(得分:2)

分面搜索是一个分析问题,这意味着尺寸设计是一个不错的选择。 Aka,你搜索的东西必须是表格形式。

在分析表中包含所有感兴趣的列。

将连续值放入存储桶。

对类别或标签等“很多”项使用布尔列,例如,如果有三个标签“foo”,“bar”和“baz”,则会有三个布尔列。

使用物化视图创建分析表。

将废话索引出来。某些数据库支持此类应用程序的索引。

只过滤一次。

联合你的结果。

为常见查询构建预先聚合的物化视图。

本文也可能对您有所帮助:https://blog.jooq.org/2017/04/20/how-to-calculate-multiple-aggregate-functions-in-a-single-query/

with filtered as (
    select
    *
    from cars_analytic
    where
        [some search conditions]
)

--for each facet:

select
    'brand' as facet,
    brand as value,
    count(*) as count
from
    filtered
group by
    brand

union

select
    'cool-tag' as facet,
    'cool-tag'as value,
    count(*) as count
from
    filtered
where
    cool_tag

union

...


-- sort at the end
order by
    facet,
    count desc,
    value

100,000条记录,5个方面在~150毫秒

答案 3 :(得分:0)

关于计数,为什么要通过SQL拉它们?无论如何,你必须遍历代码中的结果集,那么为什么不在那里计算呢?

我正在使用这种方法在我正在开发的分面搜索应用程序中,它运行正常。唯一棘手的部分是将代码设置为不输出构面,直到它到达新的构面。此时,输出facet以及为其找到的行数。

此方法假设您正在撤回所有匹配项的列表,因此,多个行具有相同的构面。当您通过facet订购此结果时,很容易在代码中获得计数。