나를 똑바로 세우자.
테이블이 posts
입니다. 테이블이 posts_types
입니다. 두 사람은 posts_types_assignment
에 다 대다 참여자가 있습니다. 그리고 느린 쿼리가 있습니다.
SELECT count(*)
FROM posts p
JOIN posts_types_assigment pta1
ON p.id = pta1.post_id
JOIN posts_types pt1
ON pt1.id = pta1.post_type_id
AND pt1.type = 'language'
AND pt1.name = 'English'
JOIN posts_types_assigment pta2
ON p.id = pta2.post_id
JOIN posts_types pt2
ON pt2.id = pta2.post_type_id
AND pt2.type = 'tag'
AND pt2.name = 'awesome'
그리고 왜 그렇게 느린지 알고 싶습니다.
첫 번째 메모는 조인이 아닌 posts
테이블에 식별자가있는 경우 PostgreSQL이 훨씬 적은 작업을해야한다는 것입니다. 그러나 그것은 논쟁의 여지가 있습니다. 결정이 내려졌습니다.
필자가 더 유용한 점은 PostgreSQL에 Oracle과 유사한 쿼리 최적화 프로그램이 있다고 생각합니다. 이 경우 고려해야 할 가능한 쿼리 계획의 조합 폭발을 제한하기 위해 일부 테이블로 시작하여 한 번에 하나 이상의 데이터 집합에 반복적으로 조인하는 계획 만 고려합니다. 그러나 이러한 쿼리 계획은 여기에서 작동하지 않습니다. pt1
으로 시작하여 1 레코드를 얻은 다음 pta1
으로 이동하여 여러 레코드를 얻고 p
에 가입하고 동일한 레코드 수를 얻은 다음 pta2
에 가입하면 엄청난 수의 레코드를 얻은 다음 pt2
, 몇 개의 레코드 만 가져옵니다. pta2
에 가입하는 것은 느린 단계입니다. 데이터베이스에서 원하는 레코드를 모르기 때문에 게시물과 메타 데이터 (유형, 언어 또는 태그)의 모든 조합에 대해 임시 결과 집합을 만들어야하기 때문입니다.
이것이 실제로 문제가되는 경우 오른쪽 계획은 다음과 같습니다. pt1
을 pta1
에 가입 시키십시오. pt2
을 pta2
에 가입시킨 다음 첫 번째 쿼리의 결과에 참여한 다음 p
에 가입하십시오. 그런 다음 계산하십시오. 이것은 거대한 결과 세트를 얻지 못한다는 것을 의미합니다.
이 경우, 쿼리 최적화 프로그램에게 새로운 유형의 실행 계획을 생각하게하려면 쿼리 최적화 프로그램에 알릴 방법이 없습니다. 그러나 그것을 강제하는 방법이 있습니다.
CREATE TEMPORARY TABLE t1
AS
SELECT pta*
FROM posts_types pt
JOIN posts_types_assignment pta
ON pt.id = pta.post_type_id
WHERE pt.type = 'language'
AND pt.name = 'English';
CREATE INDEX idx1 ON t1 (post_id);
CREATE TEMPORARY TABLE t2
AS
SELECT pta*
FROM posts_types pt
JOIN posts_types_assignment pta
ON pt.id = pta.post_type_id
JOIN t1
ON t1.post_id = pta.post_id
WHERE pt.type = 'language'
AND pt.name = 'English';
SELECT COUNT(*)
FROM posts p
JOIN t1
ON p.id = t1.post_id;
임의의 오타 등을 배제하면이 기능이 다소 향상 될 수 있습니다. 그렇지 않으면 테이블의 색인을 다시 확인하십시오.btilly 노트로
쿼리 계획을 보려면 [explain] (http://www.postgresql.org/docs/9.0/static/sql-explain.html)을 수행 했습니까? –
@Sam 네, 저도 그렇게 생각합니다 (많은 곳에서 발견 한 정보에 따르면) 이것은 PostgreSQL 자체의 문제입니다. 이제 "~ COUNT (*) FROM posts"를 시도했는데 ~ 1 500 000 레코드 였고 COUNTing은 ~ 9 초가 걸렸습니다. 두 번째로 (Postgre가 아마도 쿼리를 캐시하거나) 약 2 초가 걸렸다. 어쨌든 2 초는 매우 느립니다. –
인덱스를 만들려고 했습니까? 부분적인 인덱스를 잊지 마라. 데이터의 하위 집합 만 인덱싱하면 큰 성능 차이가 발생할 수 있습니다. 이러한 명확한 작업을 수행했지만 여전히 개선되지 않으면 추가 도움말 (테이블 스키마, 샘플 데이터, 샘플 쿼리, 설명 계획, postgresql 버전 등)을 추가로 게시하는 것이 좋습니다. –