2016-12-24 91 views
0

表:文章在Postgres中,如何匹配多个“标签”以获得最佳性能?

+--------+------+------------+ 
| id  | title| created | 
+--------+------+------------+ 
| 201 | AAA | 1482561011 | 
| 202 | BBB | 1482561099 | 
| 203 | CCC | 1482562188 | 
+--------+------+------------+ 

表:引用的Tagging

+-----------+------+ 
| articleid | tagid| 
+-----------+------+ 
| 201 | 11 | 
| 201 | 12 | 
| 202 | 11 | 
| 202 | 13 | 
| 202 | 14 | 
+-----------+------+ 

现在,如果给定的3标签ID,什么是最好的索引设计和查询,选择最新的10篇文章是每篇文章匹配3个标签ID在同一时间
我知道可以有几种方法可以做到这一点,但我关于性能,考虑可能有成千上万的文章中的每个标签

+0

'查询选择最新的10篇文章' - 请解释你如何定义'最新文章'?在某个表格中是否有日期栏,这个问题没有显示?或'最新'是否意味着'id'列中的最高值? – krokodilko

+0

@krokodilko我在表格中添加了“创建”列。并且是最新的是id列中的最高值。该id是“int serial”。 –

+0

这可能对您有意思:http://www.databasesoup.com/2015/01/tag-all-things.html –

回答

0

你需要articles.created有一个指标进行排序,而另一在taggings(articleid, tagid)唯一索引查询:

CREATE INDEX ON articles(created); 
CREATE UNIQUE INDEX ON taggings(articleid, tagid); 

接下来,只要有三个taggings表的别名选择查询:

SELECT a.* FROM articles a, taggings t1, taggings t2, taggings t3 
    WHERE a.id=t1.articleid AND a.id=t2.articleid AND a.id=t3.articleid 
    AND t1.tagid=111 AND t2.tagid=222 AND t3.tagid=333 
    ORDER BY created DESC LIMIT 10; 
+0

表现明智的(多)连接非常糟糕。 –

1
select distinct on (a.id) a.* 
from articles a 
    join taggings t on t.articleid = a.id 
group by a.id 
having array_agg(t.tagid order by t.tagid) = array[11,13,14] 
order by a.id, a.created 
limit 10; 

taggings (articleid, tagid)上的索引将对此有所帮助。

请注意,上面的文章与正好是这三个标签。如果你想找到那些至少这三个标签(甚至更多),你可以改变having子句使用“包含”操作符:

select distinct on (a.id) a.* 
from articles a 
    join taggings t on t.articleid = a.id 
where t.tagid in (11,13,14) 
group by a.id 
having array_agg(t.tagid) @> array[11,13,14] 
order by a.id, a.created 
limit 10; 

在这种情况下,order byarray_agg()是没有必要的

相关问题