2011-01-24 7 views
0

다음 쿼리는 필요한 정보를 얻습니다. 그러나 테이블이 커지면 코드가 느려지고 느려집니다. 나는 그것이이 쿼리라고 생각하고있다. 이 방법을 사용하면 효율성을 높일 수 있습니까? 하위 쿼리 대신 조인을 사용하는 방법에 대해 많이 들었지만, 어떻게 수행해야하는지 알지 못합니다.이 쿼리는 어떻게 최적화합니까?

SELECT * FROM 

    (SELECT MAX(T.id) AS MAXid 
    FROM transactions AS T 
    GROUP BY T.position 
    ORDER BY T.position) AS result1, 

    (SELECT T.id AS id, T.symbol, T.t_type, T.degree, T.position, T.shares, T.price, T.completed, T.t_date, 
    DATEDIFF(CURRENT_DATE, T.t_date) AS days_past, 
    IFNULL(SUM(S.shares), 0) AS subtrans_shares, 
    T.shares - IFNULL(SUM(S.shares),0) AS due_shares, 

    (SELECT IFNULL(SUM(IF(SO.t_type = 'sell', -SO.shares, SO.shares)), 0) 
    FROM subtransactions AS SO WHERE SO.symbol = T.symbol) AS owned_shares 

    FROM transactions AS T 
    LEFT OUTER JOIN subtransactions AS S 
    ON T.id = S.transid  
    GROUP BY T.id 
    ORDER BY T.position) AS result2 

    WHERE MAXid = id 
+1

색인을 사용하여 테이블의 CREATE 문을 게시 할 수 있습니까? –

답변

0

귀하의 코드 :

(SELECT MAX(T.id) AS MAXid 
    FROM transactions AS T  [<--- here ] 
    GROUP BY T.position 
    ORDER BY T.position) AS result1, 

    (SELECT T.id AS id, T.symbol, T.t_type, T.degree, T.position, T.shares, T.price, T.completed, T.t_date, 
    DATEDIFF(CURRENT_DATE, T.t_date) AS days_past, 
    IFNULL(SUM(S.shares), 0) AS subtrans_shares, 
    T.shares - IFNULL(SUM(S.shares),0) AS due_shares, 

    (SELECT IFNULL(SUM(IF(SO.t_type = 'sell', -SO.shares, SO.shares)), 0) 
    FROM subtransactions AS SO WHERE SO.symbol = T.symbol) AS owned_shares 

    FROM transactions AS T  [<--- here ] 

공지 사항 난 당신의 코드에 추가 [<---- here ]마르크.

첫 번째 T은 어떤 식 으로든 두 번째 T과 관련이 없습니다. 그들은 동일한 상관 별명을 가지며 동일한 테이블을 참조하지만 완전히 독립적 인 선택 및 결과입니다. 처음에 일을하는지 그래서

, 상관는 하위 쿼리는 transactions의 모든 positions의 최대 ID를 받고있다.

그리고 당신은 (result2는이 subtransactions 모든 transaction.position의 조인 될 일이있는) result2 모든 transaction.position.max(id)들에 참여하고 있습니다. (그리고 내부 order by도 무의미하고 비용이 많이 드는이지만, 그 주요 문제가되지 않습니다.)

당신은 모든에 대한 모든 transaction.position.max(id)에 가입하고 (어떤 결과 2 선택을). 홈 점점 후 편집에

: 좋아, 당신은 Cartesianing하지 않을는 "여기서 MAXid = ID는"result2result1 가입 않습니다. 그러나 두 쿼리 모두에 여전히 transaction의 모든 행을 롤업하고 있습니다. 그래서 데카르트을 받고있어

가입 - 모든 result1은 (아무것도, 예를 들어, 데이터베이스를 알려줍니다들이 위치 (최대) ID로 또는 합류되어야한다 그) 무조건, 모든 result2에 합류했다.

따라서 이라는 고유 한 숫자가 transaction 인 경우 100 개의 행이 생성됩니다. 1000 개의 고유 한 위치, 백만 개의 행. 기타

이와 같은 복잡한 쿼리를 작성하려는 경우 간단한보기에서 작성하면 훨씬 쉽습니다. 특히 각보기를 자체적으로 테스트하여 합리적인 결과를 얻고보기에 합류 할 수 있습니다.

+0

집계 함수 ('SUM()')를 사용하기 때문에보기가 끔찍한 성능을 보일 것입니다. –

+0

데이터베이스에 따라 다릅니다. 어쨌든, 정확하고 느리게하는 것이 더 빠르다가 나중에 천천히 최적화하는 것이 빠르거나 틀리게하는 것보다 낫습니다. – tpdi

+0

나는 당신이 제안한 변화를 만들었지 만, 성능에는 변화가 없었습니다. 그것은 거대한 천천히 일으키는 특정 쿼리가 아니라는 것이 밝혀졌습니다. 그것은 다른 테이블을 모두 액세스하는 또 다른 쿼리입니다. :( – Drewneedshelp

0

필자는 저장된 프로 시저를 사용하여 쿼리를 더 작은 청크로 분할합니다. 예를 들어 트랜잭션에서 최대 ids를 가져 와서 테이블 변수에 넣으십시오. 그런 다음 이것을 서브 트랜잭션과 조인하십시오. 이렇게하면 당신과 컴파일러가 무슨 일이 일어나고 있는지 쉽게 알 수 있습니다. 또한 인덱스가 테이블에 무엇을 알고하지 않고 더 많은 조언을 제공하기 어렵다

0

코드에 벤치 마크 기능을 넣으십시오. 그런 다음 코드의 각 섹션에 속도 저하가 발생하는 위치를 결정하십시오. 종종 느린 속도는 처음 추측 한 것과 다른 쿼리에서 발생합니다. stackoverflow 게시하기 전에 최적화해야 할 올바른 쿼리를 결정하십시오.

관련 문제