문제

좋아, 여기에 내가 지금 당장 45,000 레코드를 가지고 있고 65MB의 크기가있는 테이블에서 실행중인 쿼리가 있습니다.

SELECT count(payment_id) as signup_count, sum(amount) as signup_amount
FROM payments p
WHERE tm_completed BETWEEN '2009-05-01' AND '2009-05-30'
AND completed > 0
AND tm_completed IS NOT NULL
AND member_id NOT IN (SELECT p2.member_id FROM payments p2 WHERE p2.completed=1 AND p2.tm_completed < '2009-05-01' AND p2.tm_completed IS NOT NULL GROUP BY p2.member_id)

그리고 당신이 상상할 수도 있고 상상할 수 있듯이 - 그것은 MySQL 서버를 정지 상태로 질식시킵니다 ...

그것이하는 일 - 그것은 단순히 가입 한 신규 사용자의 수를 가져오고, 적어도 하나의 "완료된"결제를하고, tm_completed는 비어 있지 않으며 (완료된 지불을 위해서만 인구가 있기 때문에), 멤버가 가지고있는 멤버가 보유한 (임베디드 선택) 이전에 "완료된"결제가 없었습니다. 그는 새로운 회원이라는 것을 의미합니다 (시스템이 재조정하고 무엇이든지,이를 방금 재조정 한 기존 회원과 청구 된 신입 회원을 구별 할 수있는 유일한 방법입니다. 처음).

이제이 쿼리를 최적화하여 자원이나 무언가를 적게 사용할 수있는 가능한 방법이 있습니까?

더 이상 명확히하기 위해 정보가 없습니까? 알려줘요...

편집하다:

다음은 해당 테이블에 이미 인덱스입니다.

1 차 1 차 46757 Payment_ID

member_id index 23378 member_id

Payer_id Index 11689 Payer_id

쿠폰 _id 색인 1 쿠폰 _id

tm_added index 46757 tm_added, product_id

tm_completed index 46757 tm_completed, product_id

도움이 되었습니까?

해결책

그런 종류의 IN Subquies는 MySQL에서 약간 느립니다. 나는 이것처럼 그것을 다시 표현할 것이다 :

SELECT COUNT(1) AS signup_count, SUM(amount) AS signup_amount
FROM   payments p
WHERE  tm_completed BETWEEN '2009-05-01' AND '2009-05-30'
AND    completed > 0
AND    NOT EXISTS (
           SELECT member_id
           FROM   payments
           WHERE  member_id = p.member_id
           AND    completed = 1
           AND    tm_completed < '2009-05-01');

수표 'tm_completed IS NOT NULL'당신의 BETWEEN 상태.

또한 색인이 있는지 확인하십시오.

(tm_completed, completed)

다른 팁

하위 퀘스트가 필요하지 않은이 솔루션을 구성하는 것이 즐거웠습니다.

SELECT count(p1.payment_id) as signup_count, 
       sum(p1.amount)       as signup_amount  

  FROM payments p1
       LEFT JOIN payments p2 
       ON p1.member_id = p2.member_id
   AND p2.completed = 1
   AND p2.tm_completed < date '2009-05-01'

 WHERE p1.completed > 0
   AND p1.tm_completed between date '2009-05-01' and date '2009-05-30'
   AND p2.member_id IS NULL;

하위 쿼리와 함께 사용하지 마십시오. MySQL은 이러한 우물을 최적화하지 않습니다 (5.4와 6.0의 최적화가 있지만 이와 관련하여 보류 중입니다. 여기). 이것을 가입으로 다시 작성하면 아마도 성능 향상이 될 것입니다.

SELECT count(payment_id) as signup_count, sum(amount) as signup_amount
FROM payments p
LEFT JOIN (SELECT p2.member_id
          FROM payments p2
          WHERE p2.completed=1
          AND p2.tm_completed < '2009-05-01'
          AND p2.tm_completed IS NOT NULL
          GROUP BY p2.member_id) foo
ON p.member_id = foo.member_id AND foo.member_id IS NULL
WHERE tm_completed BETWEEN '2009-05-01' AND '2009-05-30'
AND completed > 0
AND tm_completed IS NOT NULL

둘째, 나는 당신의 테이블 스키마를 봐야 할 것입니다. 인덱스를 사용하고 있습니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top