2011-06-13 5 views
7

postgresql에서 두 개의 거의 동일한 테이블간에 diff를 얻으려고합니다. 내가 실행하고 현재 쿼리는 다음과 같습니다PostgreSQL UNION은 개별 쿼리를 실행하는 데 10 배의 시간이 걸립니다.

SELECT * FROM tableA EXCEPT SELECT * FROM tableB; 

SELECT * FROM tableB EXCEPT SELECT * FROM tableA; 

위의 쿼리의 각 실행하는 데 약 2 분 소요 (그것의 큰 테이블)

나는 두 가지를 결합하고 싶었다 쿼리를 통해 시간을 절약하고 싶습니다. 따라서 시도해 보았습니다.

SELECT * FROM tableA EXCEPT SELECT * FROM tableB 
UNION 
SELECT * FROM tableB EXCEPT SELECT * FROM tableA; 

그리고 작동하는 동안 실행하는 데 20 분이 걸립니다. 필자는 각 쿼리를 개별적으로 실행하는 데 소요되는 시간이 최대 4 분이 걸릴 것으로 예상합니다.

UNION이 그렇게 오래 걸리는 작업이 추가 되었습니까? 아니면 내가 속도를 낼 수있는 방법이 있습니까? (UNION의 유무에 관계없이)?

업데이트 : UNION ALL을 사용하여 쿼리를 실행하면 각 쿼리를 실행하는 데 거의 4 분의 1이 걸리므로 UNION (모두)이 속도를 향상시키지 못한다고 올바르게 수정합니까?

+0

생략해야하는'tableA' 또는'tableB'에만 중복이 있습니까? 그렇지 않으면'UNION ALL'을 시도하십시오. –

+0

@ScrumMeister : 나는 이걸 전에 생각하지 못했습니다. union은 단일 테이블에서 중복 된 것을 제거합니까? 나는 그것이 두 개의 결합 표 사이의 중복 만 제거한다고 생각했습니다. 나는 그것을 연구해야 할 수도 있습니다. – RThomas

+0

'EXPLAIN ANALYZE'의 출력을 게시 할 수 있습니까? –

답변

11

귀하의 "추가 작업"질문과 관련하여. 예. Union은 두 개의 쿼리를 결합 할뿐만 아니라 중복을 제거하고 제거합니다. 별개의 문장을 사용하는 것과 같습니다.

특히 "except all"과 함께 사용하면 특히 빠릅니다.

더 여기 읽기 : 제 1 및 제 2 쿼리의 결과를 결합하는 것 외에도 http://www.postgresql.org/files/documentation/books/aw_pgsql/node80.html

+0

방금 ​​"SELECT * FROM tableA SELECT * FROM tableB UNION ALL SELECT * FROM tableB EXCEPT SELECT * FROM tableA;"를 실행했습니다. 그것은 15 분이 걸렸으므로 두 쿼리를 따로 따로 실행하는 것만 큼 빠른 속도로 실행됩니다. – lanrat

+0

정답으로 선택하고 있지만 여전히 쿼리를 실행하면 속도가 빨라질 것입니다. – lanrat

+0

@RThomas에'union all '을 추가하면 여분의 값도 추가됩니다. 고유 값을 원하면 어떻게합니까? – Lokesh

3

는 기본적으로 UNION 또한 중복 레코드를 제거합니다. (http://www.postgresql.org/docs/8.1/static/sql-select.html 참조). 두 개의 쿼리 사이에 중복 된 레코드를 확인하는 데 필요한 추가 작업은 아마도 추가 시간의 원인 일 것입니다. 이 상황에서는 중복 레코드가 없어야하므로 중복을 찾는 추가 작업은 UNION ALL을 지정하면 피할 수 있습니다.

SELECT * FROM tableA EXCEPT SELECT * FROM tableB 
UNION ALL 
SELECT * FROM tableB EXCEPT SELECT * FROM tableA; 
+0

내 답변을 입력하는 데 약간 느린 것 같습니다. 명성을 lazyDBA에 – dave

-2

당신은 TABLEA FULL OUTER 만 1 테이블 스캔 당신의 (a propre와 조인 조건) 원하는 것을 줄 것이다 TableB의를 가입 사용할 수 있습니다, 아마 위의 두 쿼리를보다 빠르게 할 것이다.

자세한 내용을 보내주십시오.

2

귀하의 코드가 의도 한 결과 세트를 반환한다고 생각하지 않습니다. 나는 당신이 이것을하고 싶어한다고 생각합니다 :

SELECT * 
    FROM (
     SELECT * FROM tableA 
     EXCEPT 
     SELECT * FROM tableB 
     ) AS T1 
UNION 
SELECT * 
    FROM (
     SELECT * FROM tableB 
     EXCEPT 
     SELECT * FROM tableA 
     ) AS T2; 

다시 말하면 상호 배타적 인 멤버가 필요합니다.그렇다면, 당신은 SQL 관계형 연산자 우선 순위에 읽을 필요) 그리고 당신이있을 때, 당신은 위의 합리화 될 수 실현할 수 있습니다 하위 쿼리를 사용하여,

SELECT * FROM tableA 
UNION 
SELECT * FROM tableB 
EXCEPT 
SELECT * FROM tableA 
INTERSECT 
SELECT * FROM tableB; 

FWIW을 (파생 테이블 T1T2)는 명시 적으로 관계 연산자의 우선 순위는, 원래 쿼리가 이것이다 (그렇지 않으면 암시 무엇을 것) 표시합니다 :

,369 :

SELECT * 
    FROM (
     SELECT * 
      FROM (
       SELECT * 
        FROM tableA 
       EXCEPT 
       SELECT * 
        FROM tableB 
       ) AS T2 
     UNION 
     SELECT * 
      FROM tableB 
     ) AS T1 
EXCEPT 
SELECT * 
    FROM tableA; 

위를 relationalised 할 수있다

SELECT * 
    FROM tableB 
EXCEPT 
SELECT * 
    FROM tableA; 

... 나는 의도 한 것이 아니라고 생각합니다.

+0

설명 주셔서 감사! 귀하가 제공 한 첫 번째 쿼리를 실행했지만 두 개의 개별 쿼리를 실행하는 것보다 훨씬 오래 걸립니다. 내가 실행중인 두 개의 쿼리는 정확히 내가 원하는 것입니다. 나는 단지 그것을 더 빨리 원한다. 제공된 두 번째 검색어는 1 시간 이상 걸렸으므로 중지했습니다 (10 분 미만의 다른 모든 위치) – lanrat

관련 문제