2010-02-23 3 views
1

내 응용 프로그램에는 응용 프로그램 이벤트의 사용자 별 피드를 생성하는 데 사용되는 응용 프로그램 이벤트 테이블이 있습니다. 그것은 OR 쿼리를 사용하여 생성 되었기 때문에이 많이 사용되는 쿼리의 성능에 대해 걱정하고 있으며 내가이 오류에 접근하는지 궁금합니다.또는 PostgreSQL의 쿼리 성능 및 전략

응용 프로그램에서 사용자는 다른 사용자와 그룹을 모두 따라갈 수 있습니다. 작업이 수행 될 때 (예 : 새 게시물이 생성 될 때) actor_id이 사용자의 ID로 설정되고 subject_id이 작업이 수행 된 그룹 ID로 설정된 feed_item 레코드가 생성되고 actor_typesubject_type이로 설정됩니다 모델의 클래스 명 사용자는 그룹과 사용자 모두를 추적 할 수 있으므로 actor_id와 subject_id를 모두 확인하는 쿼리를 생성해야하며 중복을 피하기 위해 고유 한 레코드를 선택해야합니다. OR 쿼리이기 때문에 정상적인 인덱스를 사용할 수 없습니다. 그리고 작업이 수행 될 때마다 레코드가 만들어지기 때문에이 테이블에는 많은 레코드가 필요합니다.

여기에 현재 쿼리의합니다 (following 테이블 feeders에 사용자를 조인, 일명, 사용자 및 그룹)

SELECT DISTINCT feed_items.* FROM "feed_items" 
INNER JOIN "followings" 
ON (
(followings.feeder_id = feed_items.subject_id 
AND followings.feeder_type = feed_items.subject_type) 
OR 
(followings.feeder_id = feed_items.actor_id 
AND followings.feeder_type = feed_items.actor_type) 
) 
WHERE (followings.follower_id = 42) ORDER BY feed_items.created_at DESC LIMIT 30 OFFSET 0 

그래서 내 질문 :이 이후

  • 가 많이 사용되는 쿼리가있다 거기에 성능 문제가 있습니까?

  • 누락 된 부분을 간략화하거나 최적화하는 명백한 방법이 있습니까?

답변

0

성능 문제가 있는지 알아 보려면이를 확인하십시오. PostgreSQL은 explain입니다.

성능 문제를 파악하면 색인을 수정해야 할 수도 있습니다.

1

당신이 가지고있는 것은 호 ()라는 호이며 정확히 왜 그것이 나쁜 아이디어인지 알고 있습니다.

  • 피드 항목 : ID, 유형 (배우 또는 주제에 대한 A 또는 S), 하위 유형 (actor_type 및 subject_type을 대체)
이런 종류의 문제에 대한 가장 좋은 방법은 피드 항목의 동적 유형을 확인하는 것입니다

및 다음 쿼리는

SELECT DISTINCT fi.* 
FROM feed_items fi 
JOIN followings f ON f.feeder_id = fi.id AND f.feeder_type = fi.type AND f.feeder_subtype = fi.subtype 

또는 유사한된다.

이것은 당신이해야 할 일을 완전하게 또는 정확히 나타내지는 못했지만 원리는 건전합니다 : 실행중인 쿼리가 쓰여지는 방식으로 데이터 모델을 변경함으로써 OR 조건의 이유를 제거해야합니다 그것에 대하여.

+0

이 메서드를 사용하는 것처럼 나는 액터와 대상에 대해 각각 두 개의 피드 항목을 만들 필요가 있습니다. 그리고 액터와 대상이 모두 뒤따를 때 중복을 반환하므로 중복을 필터링해야합니다. 내가 완전히 기반이 아니라면, 아마도'action_id'를 가지고'SELECT feed_items. * FROM feed_items where와 같은 것을 할 필요가있을 것이다. (feed_items FROM feed_items fi JOIN f f. feeder_id = fi.id AND f.feeder_type = fi.type AND f.feeder_subtype = fi.subtype)'맞습니까? OR보다 낫지? – user279603

1

설명 문제를 분석하고 시간을 쿼리하여 설명하십시오.

아소 당신은 분석하고 벤치 마크 설명 다시

SELECT x.* FROM 
(
SELECT feed_items.* FROM feed_items 
INNER JOIN followings 
ON followings.feeder_id = feed_items.subject_id 
    AND followings.feeder_type = feed_items.subject_type 
WHERE (followings.follower_id = 42) 
UNION 
SELECT feed_items.* FROM feed_items 
INNER JOIN followings 
followings.feeder_id = feed_items.actor_id 
AND followings.feeder_type = feed_items.actor_type) 
WHERE (followings.follower_id = 42) 
) AS x 
ORDER BY x.created_at DESC 
LIMIT 30 

조합으로 쿼리를 표현하려고하지만 수 있습니다.