2017-12-08 27 views
-3

여러 테이블에서 데이터를 가져 오기 위해 여러 조인을 사용하여 쿼리를 만들었습니다. 5000+ 레코드의 경우 매우 느리게 작동합니다. 나는 쿼리에 사용 된 각 테이블에 대해 제대로 점검하고 인덱스를 설정했습니다. 여러 옵션을 사용하여이 쿼리를 최적화하려고했지만 작동하지 않아 EXPLAIN 또는 EXPLAIN EXTENDED Help를 정확히 이해하지 못했습니다.다중 자기 조인과 인덱스로 My Moodle mysql 쿼리의 속도를 높이는 방법

=====

QUERY

EXPLAIN EXTENDED 
SELECT @rownum := @rownum + 1 AS id, 
     u.id AS userid, 
     u.username AS employeeid, 
     u.firstname, 
     u.lastname, 
     u.email AS email, 
     u.city AS state, 
     c.fullname AS course, 
     c.id AS courseid, 
     c.fullname AS coursename, 
     fi2.data branchid, 
     fi3.data branchname, 
     fi6.data areaname, 
     fi7.data regname, 
     fi8.data designation, 
     fi9.data department, 
     fi10.data zone, 
     fi11.data branchcategory, 
     fi12.data branchdistrict, 
     fi13.data branchstate, 
     fi17.data gender, 
     fi21.data employeecategory, 
     fi22.data persontype, 
     fi23.data assignmentstatus, 
     fi30.data POSITION, 
     fi32.data dateofjoining, 
     fi33.data dateofbirth, 
     st.scoid, 
     st.scormid, 
     st.attempt, 
     st.value cmistarttime, 
     st5.value cmilessonstatus, 
     st5.timemodified cmitimemodified, 
     st3.value cmitotaltime, 
     st2.value cmiscore 
FROM (
     SELECT @rownum := 0 
    ) r, 
    mdl_user u 
    JOIN mdl_role_assignments ra ON ra.userid = u.id 
    JOIN mdl_context ctx ON ctx.id = ra.contextid 
    JOIN mdl_course c ON c.id = ctx.instanceid 
    JOIN mdl_scorm s ON s.course = c.id 
    JOIN mdl_scorm_scoes_track st ON st.scormid = s.id AND st.userid = u.id 
    JOIN mdl_scorm_scoes_track AS st2 ON (u.id = st2.userid AND st2.scormid 
     = s.id AND st2.scoid = st.scoid AND st2.attempt = st.attempt) 
    JOIN mdl_scorm_scoes_track AS st3 ON (u.id = st3.userid AND st3.scormid 
     = s.id AND st3.scoid = st.scoid AND st3.attempt = st.attempt) 
    JOIN mdl_scorm_scoes_track AS st5 ON (u.id = st5.userid AND st5.scormid 
     = s.id AND st5.scoid = st.scoid AND st5.attempt = st.attempt) 
    JOIN mdl_user_info_data AS fi2 ON u.id = fi2.userid 
    JOIN mdl_user_info_data AS fi3 ON u.id = fi3.userid 
    JOIN mdl_user_info_data AS fi6 ON u.id = fi6.userid 
    JOIN mdl_user_info_data AS fi7 ON u.id = fi7.userid 
    JOIN mdl_user_info_data AS fi8 ON u.id = fi8.userid 
    JOIN mdl_user_info_data AS fi9 ON u.id = fi9.userid 
    JOIN mdl_user_info_data AS fi10 ON u.id = fi10.userid 
    JOIN mdl_user_info_data AS fi11 ON u.id = fi11.userid 
    JOIN mdl_user_info_data AS fi12 ON u.id = fi12.userid 
    JOIN mdl_user_info_data AS fi13 ON u.id = fi13.userid 
    JOIN mdl_user_info_data AS fi17 ON u.id = fi17.userid 
    JOIN mdl_user_info_data AS fi21 ON u.id = fi21.userid 
    JOIN mdl_user_info_data AS fi22 ON u.id = fi22.userid 
    JOIN mdl_user_info_data AS fi23 ON u.id = fi23.userid 
    JOIN mdl_user_info_data AS fi30 ON u.id = fi30.userid 
    JOIN mdl_user_info_data AS fi32 ON u.id = fi32.userid 
    JOIN mdl_user_info_data AS fi33 ON u.id = fi33.userid 
WHERE c.id > 0 AND 
     u.id > 0 AND 
     u.deleted = 0 AND 
     u.suspended = 0 AND 
     u.confirmed = 1 AND 
     u.id <= 1000 AND 
     c.visible = 1 AND 
     st.element LIKE '%x.start.time%' AND 
     st2.element LIKE '%cmi.core.score.raw%' AND 
     st3.element LIKE '%cmi.core.total_time%' AND 
     st5.element LIKE '%cmi.core.lesson_status%' AND 
     fi2.fieldid = 2 AND 
     fi3.fieldid = 3 AND 
     fi6.fieldid = 6 AND 
     fi7.fieldid = 7 AND 
     fi8.fieldid = 8 AND 
     fi9.fieldid = 9 AND 
     fi10.fieldid = 10 AND 
     fi11.fieldid = 11 AND 
     fi12.fieldid = 12 AND 
     fi13.fieldid = 13 AND 
     fi17.fieldid = 17 AND 
     fi21.fieldid = 21 AND 
     fi22.fieldid = 22 AND 
     fi23.fieldid = 23 AND 
     fi30.fieldid = 30 AND 
     fi32.fieldid = 32 AND 
     fi33.fieldid = 33 AND 
     ra.roleid = 5 AND 
     ctx.contextlevel = 50 

==========================

mdl_scorm_scoes_track 테이블

mdl_scorm_scoes_track table

+0

는 아마도이 질문은 https://codereview.stackexchange.com에 더 적합한 내 쿼리에 잘못된 경우 알려 주시기 바랍니다 그 주제를 벗어 나 여기 넓은 조금 보인다. – Jon

+2

설명을 제공 한 것은 좋지만 기본 사항도 필요합니다. See : [매우 간단한 SQL 쿼리 인 것처럼 보이는 MCVE를 제공해야하는 이유는 무엇입니까?] (https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve- for-what-like-to-me-to-be-a-very-simple-sql-query) - 거기에 텍스트를 수정 했습니까? 말할 수는 없지만 갖고 있다면 도움이되지 않습니다. – Strawberry

+0

테이블 구조 또는 기타 세부 정보를보고 싶다면 다른 세부 정보를 공유하고 싶습니다. 실제로, 나는 전에 EXPLAIN을 사용하지 않았고 정확하게 그것이 나에게 어떤 점인지 이해하려고 노력했다. – user2791498

답변

0

당신은 자체 조인 4 방향 보이는 약 4 개 행을 식별하는 말하기의 목적 involvi 같은 userid-scormid-scoid-attempt이지만 4 가지 요소가 있습니다. 이는 4 개의 요소로 구성된 4 튜플을 얻는 데 값 비싼 방법입니다. (또한이 5 개의 열은 고유 한 키를 형성합니다.) 다른 테이블의 모든 하위 값과 함께 나타나는 하위 값이있는 행을 찾아서 SQL로 표현하는 관계 분할에 대해 읽습니다. 예를 들어 4 개의 튜플에 그룹을 지정하려면 괄호 된 요소 수 = 4가 있어야합니다. 여기서 요소는 4 개의 값 중 하나입니다.

0

예, 귀하의 가정은 정확합니다. 다음은 저의 가벼운 질문입니다. 이것은 4 방향 자체 조인이지만 다른 요소가 있습니다. 이것은 표준 테이블이며 14,000,000 레코드를 저장하므로 테이블 구조를 변경하거나 쿼리를 삽입하는 것은 매우 어렵습니다.

SELECT DISTINCT st1.* FROM mdl_scorm_scoes_track st1 
JOIN mdl_scorm_scoes_track st2 ON st1.userid = st2.userid AND st1.scormid = st2.scormid AND st1.scoid = st2.scoid AND st1.attempt = st2.attempt 
JOIN mdl_scorm_scoes_track st3 ON st1.userid = st3.userid AND st1.scormid = st3.scormid AND st1.scoid = st3.scoid AND st1.attempt = st3.attempt 
JOIN mdl_scorm_scoes_track st4 ON st1.userid = st4.userid AND st1.scormid = st4.scormid AND st1.scoid = st4.scoid AND st1.attempt = st4.attempt 
AND st1.element = 'x.start.time' 
AND st2.element = 'cmi.core.score.raw' 
AND st3.element = 'cmi.core.total_time' 
AND st4.element = 'cmi.core.lesson_status' AND st1.userid <= 10 
GROUP BY st1.userid, st1.scormid, st1.scoid, st1.attempt 

나는 또한 제안 된 방법을 시도했지만 도움이되지 않았습니다. 확인하고 아무것도

SELECT DISTINCT st1.* FROM mdl_scorm_scoes_track st1 
JOIN mdl_scorm_scoes_track st2 ON st1.userid = st2.userid AND st1.scormid = st2.scormid AND st1.scoid = st2.scoid AND st1.attempt = st2.attempt 
JOIN mdl_scorm_scoes_track st3 ON st1.userid = st3.userid AND st1.scormid = st3.scormid AND st1.scoid = st3.scoid AND st1.attempt = st3.attempt 
JOIN mdl_scorm_scoes_track st4 ON st1.userid = st4.userid AND st1.scormid = st4.scormid AND st1.scoid = st4.scoid AND st1.attempt = st4.attempt 
AND st1.element = 'x.start.time' 
AND st2.element = 'cmi.core.score.raw' 
AND st3.element = 'cmi.core.total_time' 
AND st4.element = 'cmi.core.lesson_status' AND st1.userid <= 10 
GROUP BY st1.userid, st1.scormid, st1.scoid, st1.attempt 
HAVING COUNT(*) = (
    SELECT COUNT(*) FROM mdl_scorm_scoes_track st5 
    WHERE st1.userid = st5.userid AND st1.scormid = st5.scormid AND st1.scoid = st5.scoid AND st1.attempt = st5.attempt AND st5.element = 'x.start.time' 
)