InfoGrab DocsInfoGrab Docs

라벨로 필터링

GitLab에서 이슈, 머지 리퀘스트, 에픽을 여러 라벨로 필터링하는 데이터베이스 쿼리 방식과 성능 개선 시도를 설명합니다.

소개 # GitLab에는 이슈, 머지 리퀘스트, 에픽에 할당할 수 있는 라벨 이 있습니다. 이러한 객체의 라벨은 다형성 테이블 label_links 를 통한 다대다(many-to-many) 관계입니다. 여러 라벨로 이러한 객체를 필터링하는 경우 — 예를 들어 '라벨 ~Plan과 라벨 ~backend가 모두 있는 열린 이슈' — GROUP BY 절을 포함하는 쿼리를 생성합니다. 간단한 형태로는 다음과 같습니다: SELECT issues.* FROM issues INNER JOIN label_links ON label_links.target_id = issues.id AND label_links.target_type = 'Issue' INNER JOIN labels ON labels.id = label_links.label_id WHERE issues.project_id = 13083 AND (issues.state IN ('opened')) AND labels.title IN ('Plan', 'backend') GROUP BY issues.id HAVING (COUNT(DISTINCT labels.title) = 2) ORDER BY issues.updated_at DESC, issues.id DESC LIMIT 20 OFFSET 0 구체적으로: GROUP BY issues.id 는 결과를 이슈별로 그룹화합니다. HAVING (COUNT(DISTINCT labels.title) = 2) 는 일치하는 모든 이슈에 두 라벨이 모두 있도록 보장합니다. 이 방법은 이상적인 것보다 더 복잡합니다. 쿼리 구성 시 오류가 발생하기 쉬워집니다 (예: 이슈 #15557 ). 시도 A: WHERE EXISTS # 시도 A1: WHERE EXISTS를 사용한 다중 서브쿼리 # 이슈 #37137 과 관련 머지 리퀘스트 에서 GROUP BY 를 WHERE EXISTS 의 다중 사용으로 대체하려고 시도했습니다. 위 예시의 경우, 다음과 같은 결과가 됩니다: WHERE (EXISTS ( SELECT TRUE FROM label_links INNER JOIN labels ON labels.id = label_links.label_id WHERE labels.title = 'Plan' AND target_type = 'Issue' AND target_id = issues.id)) AND (EXISTS ( SELECT TRUE FROM label_links INNER JOIN labels ON labels.id = label_links.label_id WHERE labels.title = 'backend' AND target_type = 'Issue' AND target_id = issues.id)) 이 방법은 스키마 변경 없이 작동했으며 가독성이 다소 향상되었지만, 쿼리 성능은 개선되지 않았습니다. 시도 A2: WHERE EXISTS 절에서 라벨 ID 사용 # 머지 리퀘스트 #34503 에서 A1과 유사한 접근 방식을 따랐습니다. 이번에는 EXISTS 절에서 JOIN