2017-12-08 4 views
-3

Ich habe eine Abfrage mit mehreren Joins für das Abrufen von Daten aus mehreren Tabellen erstellt. Für mehr als 5000 Einträge arbeitet es sehr langsam. Ich hatte überprüft und Indizes sind für jede Tabelle in einer Abfrage ordnungsgemäß eingerichtet. Ich habe versucht, diese Abfrage mit mehreren Optionen zu optimieren, aber es hat nicht funktioniert und ich verstehe die EXPLAIN- oder EXPLAIN EXTENDED-Hilfe nicht genau.Wie kann ich meine Moodle-MySQL-Abfrage mit mehreren Self-Joins und Index beschleunigen

=====

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 Tisch

mdl_scorm_scoes_track table

+0

Vielleicht ist diese Frage besser für https://codereview.stackexchange.com geeignet ist sein scheint ein wenig vom Thema oder breit hier. – Jon

+2

Es ist großartig, dass Sie das EXPLAIN bereitgestellt haben, aber wir brauchen auch die Grundlagen. Siehe: [Warum sollte ich ein MCVE für eine scheinbar einfache SQL-Abfrage bereitstellen?] (Https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve- for-was-scheint-mir-eine-sehr-einfache-sql-Abfrage) - und haben Sie dort einen Text redigiert? Es ist schwer zu sagen, aber nicht hilfreich, wenn Sie es getan haben. – Strawberry

+0

Ich möchte andere Details teilen, wie wenn Sie Tabellenstruktur oder andere Details sehen möchten. Eigentlich habe ich EXPLAIN nicht benutzt und versuche zu verstehen, wo genau es auf mich zeigt. – user2791498

Antwort

0

der Zweck Ihrer 4-Wege-Selbst verbinden scheint grob gesprochen vier Reihen zu identifizieren involvi Den gleichen Userid-Scormid-Scoid-Versuch, aber mit 4 verschiedenen Elementen. Das ist eine kostspielige Methode, um 4-Tupel mit 4 Elementen zu erhalten. (Darüber hinaus bilden diese 5 Spalten einen eindeutigen Schlüssel.) Lesen Sie über relationale Division, die Zeilen mit Subrow-Werten findet, die bei allen Subrow-Werten in einer anderen Tabelle erscheinen, und sie in SQL ausdrückt. ZB wollen Sie Gruppen pro 4-Tupel mit unterschiedlicher Elementanzahl = 4, wobei Element zu den 4 Werten gehört.

0

Ja, Ihre Annahme ist richtig. Folgendes ist meine Light-Version der Abfrage. Dies ist 4-Wege-Self-Join, aber mit verschiedenen Elementen. Dies ist Standardtabelle und gespeichert 14,00,000+ Datensätze, so dass es sehr schwierig für mich, Tabellenstruktur zu ändern oder Abfrage einfügen.

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 

Ich habe auch Ihren vorgeschlagenen Ansatz versucht, aber es war nicht hilfreich. Bitte überprüfen Sie und lassen Sie mich wissen, wenn etwas in meiner Anfrage falsch ist

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' 
) 
Verwandte Themen