2010-12-07 11 views
1

다음 두 쿼리를 동일한 구조로 테스트했습니다. 처음에는 4M 항목이 있고 33 초 만에 결과를 반환했습니다. 두 번째 테이블에는 29M 행이 있으며 쿼리를 실행 한 지 16 시간이 지났으므로 아직 수익을 얻지 못했습니다.쿼리 최적화

SELECT sbvpip*4 as smallbvpip,btnvpip*4 as buttonvpip, sum(amt_won)*400/count(*) AS winrate, count(*) as count 

FROM holdem_hand_player_statistics 

    JOIN (

    SELECT id_player AS pid2, id_hand AS hid, sbvpip 
    FROM holdem_hand_player_statistics 

     JOIN (
     SELECT id_player AS pid, ROUND(avg(flg_vpip::int)*25) AS sbvpip 
     FROM holdem_hand_player_statistics 
     WHERE position = 8 AND cnt_players = 6 
     GROUP BY id_player 
     ) AS auxtable 
     ON pid = id_player 

    WHERE position = 8 AND cnt_players = 6 
    ) AS auxtable2 
    ON hid = id_hand 


    JOIN (

    SELECT id_player AS pid4, id_hand AS hid2, btnvpip 
    FROM holdem_hand_player_statistics 

     JOIN (
     SELECT id_player AS pid3, ROUND(avg(flg_vpip::int)*25) AS btnvpip 
     FROM holdem_hand_player_statistics 
     WHERE position = 0 AND cnt_players = 6 
     GROUP BY id_player 
     ) AS auxtable3 
     ON pid3 = id_player 

    WHERE position = 0 AND cnt_players = 6 
    ) AS auxtable4 
    ON hid2 = id_hand 


WHERE POSITION = 0 and cnt_players = 6 



GROUP BY sbvpip,btnvpip 
ORDER BY 1,2; 

이 쿼리를 더 빠르게 실행하려면 어떻게해야합니까?

테이블이 손상 되었습니까? 한 테이블은 다른 테이블보다 7 ~ 8 배 크기지만, 처리하는 데 15000 배의 시간이 더 걸립니다. 정상입니까?

다른 의견을 환영합니다!

영어가 확실하지 않은 경우 다른 방법으로 자신을 표현하려고 노력한다는 사실을 알려주세요. id_hand, id_player 위치 : 나는 그들 중 3 인덱스이며, 사용하고있는 변수에서

:

추가 정보, 도움 주셔서 대단히 감사합니다. 기본 키는 (id_hand, id_player)입니다. 이 테이블에는 총 129 개의 열과 6 개의 인덱스가 있습니다.

두 테이블 모두에서 EXPLAIN을 실행했는데 다른 결과가 나타납니다. 결과는 gdocs 스프레드 시트에 있습니다. https://spreadsheets.google.com/ccc?key=tGxqxVNzHYznb1VVjtKyAuw&authkey=CJ-BiYkN&authkey=CJ-BiYkN#gid=0

+2

, 그것은 당신을 도울 거의 불가능하다. EXPLAIN의 결과도 표시 할 수 있습니까? –

+0

프랭크, 내가 집에 도착하면 나는이 정보를 얻고 그것을 게시 할 것이다. 감사. – joaoavf

+0

테이블에 정기적으로 진공 청소기를 사용하고 있습니까? –

답변

2

아마도 더 많은 행에 대해 더 많은 정렬 메모리를 사용하고있을 가능성이 있습니다 : work_mem 설정은 무엇입니까? 마찬가지로 버퍼 캐시와 마찬가지로 동일한 테이블을 여러 번 스캔하므로 행을 캐시에 맞추는 것이 중요 할 수 있습니다.

또한 해당 쿼리를 다시 검사하고 통계 테이블에 여러 번 가입 할 필요가없는 방법을 여러 번 찾아야합니다. 최소한의 작은 테스트 데이터와 기대되는 출력 없이는 조언하기가 어렵습니다. 어떤 버전의 PostgreSQL을 사용하고 있습니까? 8.4를 사용하면 하나의 CTE에서 Auxtable 및 auxtable3을 모두 가져올 수 있습니다.

+0

Araqnid, 집에 도착하면이 설정을 확인하겠습니다. PostgreSQL 버전도 확인 하겠지만 8.4 버전이므로 단일 CTE를 사용하여 쿼리를 작성하려고합니다. 작은 테스트 데이터와 예상되는 결과는 무엇을 의미합니까? 나는 그것을 얻을 수 있습니다. 감사. – joaoavf

3

색인 생성 중 하나가 서버에 존재하지 않거나 올바르지 않습니다.

쿼리가 차단되는 것을 차단할 수도 있습니다. 특히 거기에 앉아있는 커밋되지 않은 거래가있는 경우에 특히 그렇습니다.

+0

두 테이블은 동일한 응용 프로그램에서 만들어 졌으므로 정확히 동일한 인덱스가 있어야합니다. 이 열을 사용하는 다른 쿼리는 정상적으로 작동합니다. 그러나 색인 생성에 문제가있는 경우 어떻게 확인할 수 있습니까? – joaoavf

+0

PostgreSQL에서 색인을 찾는 방법을 잘 모르겠습니다. – HLGEM

1

쿼리가 정상적으로 보입니다. 성능 향상을 위해 @HLGEM과 같은 색인 생성을 시도해보십시오. 각 하위 쿼리를 실행하여 성능이 낮은 하위 쿼리를 확인해보십시오.

1

나는 그 쿼리를 훨씬 오래 걸릴 것으로 믿을 수 있습니다. 여러 개의 그룹에 대해 작업중인 29M 행 테이블이 있고 다른 열에서 여러 번 자체에 연결됩니다. 전체 테이블이 메모리에 맞지 않으면 행 1/7 필요하지 않은 많은 페이징이있을 수 있습니다.안쪽으로 작동, 당신은 다음과 같습니다

  1. 위치에 29M 행 테이블에서 선택 = 두 번 29M 행 테이블을 필터링 두 번
  2. id_hand 컬럼에 29M 행 테이블에 다시 연결 0 cnt_players = 6
  3. cnt_players = 6, 위치 0과 8 행의 수백만 id_hand에 그룹화 된 결과에 연결 플레이어
  4. 하여 평균 flg_vpip을 계산

은 별도의 것들로 테이블을 나눌 수 있을까요? 당신의 들판은 정확히 무엇을 의미하며 샘플 핸드는 어떻게 생겼을까요?

적어도 id_player, id_hand, position 및 cnt_players에 대한 색인이 필요합니다.

색인에 모든 입력란을 포함하는 것이 좋습니다. postgresql은 확실하지 않지만 쿼리에 필요한 모든 데이터가 인덱스에 있으면 SQL Server는 실제 테이블 데이터 페이지로드를 건너 뛸 수 있습니다. 따라서 position, cnt_players, id_player 및 flg_vpip에 대한 인덱스가있는 경우 가장 안쪽에있는 선택 항목이 더 빠를 것입니다.

내가 생각하는 더 나은 방법은 미리 쿼리를 실행하지 않을 경우 한두 개의 테이블에 미리 선택하는 것이 좋습니다. 이처럼

select id_player, position, cnt_players, 
    ROUND(avg(flg_vpip::int)*25) AS avg_vpip 
into auxtable 
from holdem oldem 
group by id_player, position, cnt_players 

alter table auxtable add constraint PK_auxtable 
    primary key clustered (id_player, position, cnt_players) 

: 당신의 데이터 모델과 인덱스에 대한 어떤 생각없이

SELECT sbvpip*4 as smallbvpip,btnvpip*4 as buttonvpip, sum(amt_won)*400/count(*) AS winrate, count(*) as count 
FROM holdem 
    JOIN (
     SELECT id_player AS pid2, id_hand AS hid, sbvpip 
     FROM holdem 
      JOIN auxtable ON auxtable.id_payer = holdem.id_player 
       and auxtable.position = holdem.position 
       and auxtable.cnt_players = holdem.cnt_players 
     WHERE holdem.position = 8 AND holdem.cnt_players = 6 
    ) AS auxtable2 ON hid = id_hand 
+0

표지 색인은 Postgres에서 도움이되지 않습니다. 불행히도 "인덱스 만 스캔"하지 않습니다. –