2011-04-19 2 views
7

2 가지 쿼리가 각각 자체적으로 매우 빠르게 실행됩니다 (2 초 미만). 그러나 하위 쿼리로 조인하려고하면 천천히 실행됩니다. 마지막으로 실행했을 때 약 68 초가 걸렸습니다. 다음은 전체 검색어입니다.2 개의 쿼리가 빠르며, 하위 쿼리로 조인 할 때 속도가 느립니다.

SELECT t.count, 
     t.total 
    FROM (SELECT t.account_number, 
       COUNT(t.id) count, 
       SUM(t.amount) total, 
       ib.id import_bundle_id 
      FROM import_bundle ib 
      JOIN generic_import gi ON gi.import_bundle_id = ib.id 
      JOIN transaction_import ti ON ti.generic_import_id = gi.id 
      JOIN account_transaction t ON t.transaction_import_id = ti.id 
      JOIN transaction_code tc ON t.transaction_code_id = tc.id 
     WHERE tc.code IN (0, 20, 40) 
     GROUP BY t.account_number) t 
    JOIN (SELECT a.account_number, 
       np.code 
      FROM import_bundle ib 
      JOIN generic_import gi ON gi.import_bundle_id = ib.id 
      JOIN account_import ai ON ai.generic_import_id = gi.id 
      JOIN account a ON a.account_import_id = ai.id 
      JOIN account_northway_product anp ON anp.account_id = a.id 
      JOIN northway_product np ON anp.northway_product_id = np.id 
     WHERE np.code != 'O1') a ON t.account_number = a.account_number 

이 쿼리는 느리게 실행되어야합니다. 놀랍지는 않습니다. 이 두 테이블이 서브 쿼리가 아닌 두 개의 개별 테이블이라면 인덱스를 account_number 열에 넣을 것입니다. 그러나 쿼리 결과에 인덱스를 넣을 수는 없으므로 그렇게 할 수 없습니다. 그게 문제의 일부라고 생각합니다. 쿼리가 느린 이유 그 외에

, 나는 이해하지 않고 나는 경우 싶지 않아하는 두 개의 요약 테이블을 추가하는 것보다 다른 그 속도를하는 방법에 대한 아이디어를 가지고 있지 않습니다 I 할 필요가 없다. 그런데

는 영어로이 쿼리는 다음과 같을 수 있습니다, "보호 계정 (코드 O1)을 당좌 대월되지 않은 계정에 대한 모든 POS 거래 (코드 0, 20, 40)를 가져옵니다."

+0

설명 결과와 테이블 구조 – Neo

+0

은 두 번째 쿼리가'account_number'에 중복을 반환 할 수 있습니까? – Quassnoi

답변

1

메인 쿼리에 체크를 넣어 :

SELECT t.account_number, 
     COUNT(t.id) count, 
     SUM(t.amount) total, 
     ib.id import_bundle_id 
FROM transaction_code tc 
JOIN account_transaction t 
ON  t.transaction_code_id = tc.id 
JOIN transaction_import ti 
ON  ti.id = t.transaction_import_id 
JOIN generic_import gi 
ON  gi.id = ti.generic_import_id 
JOIN import_bundle ib 
ON  ib.id = gi.import_bundle_id 
WHERE tc.code IN (0, 20, 40) 
     AND t.account_number NOT IN 
     (
     SELECT anp.id 
     FROM account_northway_product anp 
     JOIN northway_product np 
     ON  np.id = anp.northway_product_id 
     WHERE np.code = '01' 
     ) 
GROUP BY 
     t.account_number 

다음 인덱스를 만들기 : 쿼리에서 내가 보는 것을 바탕으로

transaction_code (code) 
account_transaction (transaction_code_id) 
account_transaction (account_number) 
+0

놀라운! 고맙습니다! –

0

이 때문에 전반적인 복잡성 MySQL이 잘못 쿼리를 최적화하는 것이 가능성이 나타납니다.

은 당신이 찾을 수 있습니다하면 최선의 선택이 단계를 실행하는 것입니다.

SELECT * INTO #query1 FROM <query1> 
SELECT * INTO #query2 FROM <query2> 
SELECT * FROM #query1 INNER JOIN #query2 ON <predicate> 


또 다른 옵션은 내가 MySQL은 그들에 대해 잘 알고 모르겠지만, 힌트를 사용할 수 있습니다. 기본적으로 각 하위 쿼리에 대해 개별적으로 생성되는 계획을 확인한 다음 다른 조인에 중첩 루프 조인 (NESTED LOOP JOIN), 병합 조인 (MERGE JOIN) 등을 사용하도록 지정합니다. 이로 인해 최적화 프로그램이 수행 할 수있는 작업이 제한되므로 '잘못'될 수 있습니다. 데이터 통계가 변경되면 응답하십시오.

+0

'MySQL'은'NESTED LOOPS'를 제외하고 아무 것도 할 수 없습니다. – Quassnoi

0

; 당신의 PK가 import_bundle 테이블에 계좌 번호가 같은

1) 보인다. 해당 열에 클러스터 된 인덱스가 필요합니다. 2) northway_product 테이블에 인덱스를 추가하고 transaction_code 테이블에 (코드)를 추가하면 도움이됩니다.

다시 가입 왜 테이블의 대부분이 이미 가입되어 있기 때문에
0

... 그냥 압정-의 ID가 이미 설정되어있는 다른 테이블. 또한 모두가 JOIN이기 때문에 LEFT 조인이 없기 때문에 원래 조인이 궁극적으로 결과 집합에 합류 했으므로 모든 조인에서 찾은 레코드 만 가져 오는 것이 암시됩니다.

또한 AND np.code! = '01'을 추가하면 해당 항목이 즉시 제외되므로 쿼리에서 원하는 항목 만 빠져 나옵니다. 따라서이 내부 "PreQuery"(앨리어싱 된 PQ)가 모든 작업을 수행합니다. 그러나 귀하 그룹은 가져 오기 번들 ID를 포함하지 않으며 귀하에 대한 잘못된 대답을 통해 MAY 할 수 있습니다. 필요에 따라 조정하십시오. 그런 다음 결과는 두 개의 열만 가져옵니다. 여러 행을 반환하지만 계정 또는 총계에 대한 컨텍스트가없는 개수와 총계입니다.하지만 사용자가 적합하다고 생각하면 조정할 수 있습니다.

SELECT PQ.count, 
     PQ.total 
    FROM (SELECT STRAIGHT_JOIN 
      t.account_number, 
      COUNT(t.id) count, 
      SUM(t.amount) total, 
      ib.id import_bundle_Id 
     FROM 
      transaction_code tc 
       join account_transaction t 
        on tc.id = t.transaction_import_id 
       join transaction_import ti 
        on t.transaction_import_id = ti.id 
       join generic_import gi 
        on ti.generic_import_id = gi.id 
       join import_bundle ib 
        on gi.import_bundle_id = ib.id 
       join account_import ai 
        on gi.id = ai.generic_import_id 
       join account a 
        on ai.id = a.account_import_id 
       join account_northway_product anp 
        on a.id = anp.account_id 
       join northway_product np 
        on anp.northway_product_id = np.id 
        AND np.code != '01' 
     where 
      tc.code in (0, 20, 40) 
     group by 
      t.account_number) PQ 
관련 문제