2017-01-07 1 views
1

나는 다음과 같은 유형의 쿼리를 실행해야합니다 쿼리가 느린포스트 그레스 (크로스가 큰 테이블에 조인)

SELECT * FROM A CROSS JOIN B WHERE myfunction(A.x,B.y) = Z 

때문에 내가 속도를 사용할 수있는 모든 프로세서를 사용하고 싶습니다. 필자는 관계형 데이터베이스에 대한 기본적인 지식 만 보유하고 있으므로 "명백한"주석도 환영합니다.

  • 포스트 그레스 V 9.4.4 (업그레이드 인해 일부 제약 옵션을 선택하지 않습니다)
  • A가 3 만 개 달러 행이
  • B 100,000 행이있을 수 있습니다 (그러나 미래에 10M 행처럼 가질 수)
  • A, B는 인덱스 된 열을 가지고 있습니다.
  • myfunction (Ax, By)은 Ax의 인덱스를 이용합니다 - 없으면 훨씬 더 느려집니다.

합리적인 해결책은 무엇입니까? 현재 제안 된 순진한 분할로 50 개의 프로세서를 사용하는 10k x 2M 쿼리는 약 20 분이 걸렸습니다.

병렬 부분에서 B의 크로스 조인을 실행하는 것이 좋습니다. B는 ID의 값 (정수 기본 키)

SELECT * FROM A CROSS JOIN B WHERE myfunction(A.x,B.y) = Z AND A.id BETWEEN N and M. 

와 GNU 병렬 명령을 사용하여 실행 복수 "를 subqueryNumberX.sql MYDATABASE -d psql의"로 분할된다.

몇 가지 질문 :

  1. 내가 인덱스 테이블 T를 가지고 T의 인덱스 검색에 사용되는 것이 다른 쿼리 내에서에서 SELECT를 사용하는 경우? 또는이 subELECT가 그것을 파괴합니까?

  2. 위의 쿼리에서 테이블의 일부를 선택할 것입니다 (어디에서 N 및 M 사이의 A.id) 인덱스 사용을 방해합니까?

  3. 테이블에 대한 (느린) 크로스 조인이 진행 중일 때 다른 테이블 (크로스 조인)에서 이러한 테이블에 액세스 할 수 있습니까?

+1

어떻게 'myfunction()'이 색인을 사용합니까? 배후에서 무엇을하고 있나. 크로스 조인에 3 백만 행과 10 천 개의 행이있는 경우 크로스 조인은 3,000 억 개의 행 (3E11 행)을 처리합니다. 행당 1000 밀리 초 (1 초당 1 초), 1 년에 3 초 7 초, 그리고 1000 개의 CPU를 사용할 수 있다고 생각하면 10 년 후에 답변을 얻을 수 있습니다. 시스템이 중간에 업그레이드되어야하거나 보안 패치가 수정되지 않으면 100 배나 많은 데이터를 얻을 때 다음 천년의 시작에 대한 대답을 얻을 수 있습니다. 문제가 생겼어! –

+1

조인을 수행하려면 함수 'myfunction'을 100k * 10M = 1,000000000000 번 호출해야합니다. 1 호출에 1 밀리 초만 걸리면 1 CPU에서이 조인을 처리하려면 1,000,000,000 초 (11,574 일)가 필요합니다. 11574 개의 프로세서를 구입하면 쿼리에 1 일 (24 시간)이 걸리며 함수의 1 회 호출에는 1 밀리 초 밖에 걸리지 않습니다. 하지만 1 밀리 초 대신 200 밀리 초가 걸리면이 계산을 직접 수행 할 수 있습니다. – krokodilko

+0

함수가 계산에 필요한 시간을 추정하는 데 오류가 있어야합니다. postgres는 이전 계산에서 얻은 결과를 기억하고있는 것으로 보입니다. 위의 질문에서 제안한 순진한 분할로 50 개의 프로세서를 사용하는 10k x 2M 쿼리는 약 20 분이 걸렸습니다. SQL에 대해 더 많이 알고 있다면 아마도 그것을 향상시킬 수있을 것입니다 (위의 질문 참조). –

답변

0

귀하의 질문은 (아직) 다소 모호합니다. 크로스 조인을 들어

  1. , 인덱스는 반드시 많이 사용하지 않은,하지만 색인 열과 쿼리 테이블의 행의 크기에서 참조 된 컬럼에 따라 달라집니다. 인덱스가 관련 열에 있다면 최적화 프로그램이 '전체 테이블 스캔'대신 '인덱스 만'스캔을 수행하고 적은 양의 I/O를 활용할 수 있습니다. 그러나 SELECT *이 있으므로 AB에서 모든 열을 선택하므로 전체 행을 읽어야합니다 (2 번 참조). 질의에 하위 선택이 없으므로 하위 선택으로 무엇인가를 파괴하는 것에 대해 묻는 것은 신비로운 일입니다.

    SELECT * 
        FROM (SELECT * FROM A WHERE A.id BETWEEN N AND M) AS A1 
    CROSS JOIN B 
    WHERE myFunction(A1.x, B.y) = Z 
    

    그러나, 자동으로 그렇게 할 것 미약 최적화 될 것이다 :

  2. 명목상, 당신이에 WHERE 절을 이동에서 일부 이익을 얻을 수 있습니다와 같은 서브 선택합니다.범위 조건에 따라 A.id의 인덱스가 유용 할 수 있습니다. 특히 M과 N이 A.id의 총 값 범위 중 작은 부분을 나타내는 경우 따라서 옵티마이 저는 쿼리의 속도를 높이기 위해 A.id의 인덱스를 리딩 또는 독점 구성 요소로 사용해야합니다. 이 조건은 인덱스의 사용을 막지는 못합니다 - 인덱스는 거의 틀림없이 사용되지 않습니다.

  3. 느린 쿼리는 다른 쿼리를 금지하지 않습니다. 실행 중 업데이트를 금지하거나 DBMS의 MVCC (다중 버전 동시성 제어) 메커니즘을 강조 할 수 있습니다.