2016-12-24 4 views
0

테이블 : 기사Postgres에서 최상의 성능을 위해 여러 "태그"를 일치시키는 방법은 무엇입니까?

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

테이블 : taggings 이제

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

3 태그 ID 주어진다면, 최적의 인덱스 디자인 및 쿼리는 각 기사가 일치 최신 10 개 기사를 선택하는 것입니다 동시에 3 개의 태그 ID?
나는 그것을 할 수있는 몇 가지 방법이있을 수 있습니다 알고 있지만 나는 성능에 관한

+0

'최신 기사 10 개 선택 '-'최신 기사 '를 어떻게 정의 하시겠습니까? 질문에 표시되지 않는 일부 테이블에 날짜 열이 있습니까? 아니면 '최신'은'id' 칼럼에서 가장 높은 값을 의미합니까? – krokodilko

+0

@krokodilko "created"컬럼을 테이블에 추가했습니다. 그리고 예 최신 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; 

경우에서 array_agg()에 대한 order by가 필요하지 않습니다