2016-12-24 88 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()是沒有必要的

相關問題