2012-03-13 3 views
1

MySQL 쿼리에 끔찍한 시간을 보내고 있습니다. 나는 내 주말 대부분을 보내고 오늘이 쿼리를 좀 더 빨리 실행하려고 시도하고있다. 나는 그것을 더 빨리 만들었지 만, 내가 더 잘 만들 수 있다는 것을 안다.MySQL 쿼리 최적화 - 무작위 기록

SELECT m.id,other_fields,C.contacts_count FROM marketingDatabase AS m 
LEFT OUTER JOIN 
(SELECT COUNT(*) as contacts_count, rid 
    FROM contacts 
    WHERE status = 'Active' AND install_id = 'XXXX' GROUP BY rid) as C 
ON C.rid = m.id 
WHERE (RAND()*2612<50) 
    AND do_not_call != 'true' 
    AND `ACTUAL SALES VOLUME` >= '800000' 
    AND `ACTUAL SALES VOLUME` <= '1200000' 
    AND status = 'Pending' 
    AND install_id = 'XXXXX' 
ORDER BY RAND() 

난 'install_id', '장르'과 '상태'하지만 EXPLAIN (가)는 9100 행에 기초하여 정렬 된 표시에 인덱스를 갖는다. 설명 내

은 여기에 있습니다 : https://s3.amazonaws.com/jas-so-question/Screen+Shot+2012-03-13+at+12.34.04+AM.png

아무도 내가 조금 더 빨리이 만들기 위해 무엇을 할 수 있는지에 대한 어떤 제안이? 쿼리의 전체적인 요점은 판매량, 상태 및 do_not_call과 같은 특정 기준과 일치하는 계정 레코드 (install_id)에서 임의의 레코드를 선택하는 것입니다. 저는 현재 25 개의 레코드를 모으고 캐싱 (PHP 사용)하기 때문에 매번 25 회의 요청을 한 번만 실행해야합니다. 그러나 이미 하루에 수천 개의 요청을 처리하고 있습니다. 현재 실행하는 데 0.2 초가 걸립니다. ORDER BY RAND()를 사용하여 이미 주요 성능에 치중하고 있지만, 25 행을 정렬하는 것으로 나타났습니다.

도움을 미리 감사드립니다.

** 편집 : 'contact_sort'색인이 'contacts'테이블에 있고, 색인에 install_id, status 및 rid가 있음을 잊어 버렸습니다. (레코드 ID는 marketingDatabase에서 레코드를 참조하므로 연락처가 속한 레코드를 알 수 있습니다.

** EDIT 2 : 쿼리의 2612 숫자는 기준 (install_id, status, actual sales)과 일치하는 marketingDatabase의 행 수를 나타냅니다 볼륨 등)

+0

http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html을 참조하십시오. GROUP BY 및 색인을 사용할 때 발생하는 제한 사항과 복잡성이 있습니다. 매뉴얼 인용 "GROUP BY에 인덱스를 사용하기위한 가장 중요한 전제 조건은 모든 GROUP BY 컬럼이 동일한 인덱스의 속성을 참조하고 인덱스가 해당 키를 순서대로 저장한다는 것입니다 (예 : 이것은 BREE 인덱스이며 HASH가 아닙니다. 색인)." 비 인덱싱 필드로 그룹화하고 하위 쿼리에서 전체 테이블을 선택하고 순서를 지정합니다. RAND()에 의한 정렬 또한 나쁜 생각이라고 생각합니다. – fred2

+0

ORDER BY RAND()는 매우, 매우 나쁜 아이디어입니다 (http://www.webtrenches.com/post.cfm/avoid-rand-in-mysql). – budwiser

+0

그래, ORDER BY RAND()가 25 개의 행만 주문했기 때문에 읽었지 만 나쁜 아이디어는 아닙니다. 그렇게 큰 거래는 아닙니다. 내가 잘못? 문제를 해결하고 임의의 레코드를 얻으려면 어떻게해야합니까? 간격없이 자동 증가하는 열이 없습니다 ... 내 ID 열은 자동 증가하지만 행이 삭제 된 간격이 있습니다. – user1265617

답변

0

내가 몇 쿼리 주위 연주, 나는 당신이 이제까지 인덱스 쿼리를 얻을 수있을 거라 생각하지 않습니다에 복합 인덱스 (install_id, 상태,`실제 판매의 VOLUME`) 특히 WHERE 절과 ORDER BY 절에서 RAND()를 사용할 때 특히 그렇습니다. 가능하다면 PHP 로직에서 무작위 요소를 소개하고 두 개의 간단한 쿼리가 하나의 상당히 복잡한 쿼리보다 더 의미가 있는지 살펴 봅니다. 그것에 덧붙여, 당신은 무작위 결과 세트에 LEFT OUTER JOIN을 가지고 있으며, 이는 또한 많은 일을해야만하는 작업량을 증가시킬 수 있습니다.

요약하면, 내 생각 엔 RAND를 제외하고 LEY OUTER JOIN을 제거 할 수 있는지 다시 작성해야합니다. 그 사이에 약간의 PHP가있는 두 개의 간단한 인덱스 된 쿼리가 훨씬 더 좋을 수 있습니다.

+0

좋습니다. 이것에 대해 어떻게 생각해야합니까? 조건을 만족하는 DB의 모든 레코드를 쿼리 한 다음 array_rand()를 사용하여 임의의 요소를 선택합니다. – user1265617

+0

말하기 어렵습니다. 왜냐하면 왜 당신이 무작위 요소가 필요한지 정말로 알지 못하기 때문에 그렇습니다. 그렇습니다. 그건 합리적으로 들립니다. 2612 개의 항목 만 있으므로 전체 표를 반환하는 것은 너무 끔찍하지 않습니다 (항목에 따라 다름). 최소한 질의는 캐시 될 것이고, 아마도 MySQL과 아마도 PHP의 관점에서의 doddle 일 것이다. – fred2

1

나는 당신의 인덱스 정의가 표시되지 않기 때문에, 나는 그들이이 올바른지 확인 쿼리는 다음 인덱스 혜택을 누릴 것 아니다 :.

  1. 복합 인덱스 (install_id, 상태, rid)를 contacts

  2. marketingDatabase

+0

그래, 그게 내가 현재 색인을 위해 가지고있는 것과 정확히 일치한다. – user1265617