2017-12-08 12 views
-3

複数のテーブルからデータを取得するために複数の結合を持つクエリを作成しました。 5000以上のレコードでは非常に遅いです。私はチェックし、インデックスでは、クエリで使用される各テーブルに対して適切に設定されています。私は複数のオプションでこのクエリを最適化しようとしましたが、うまくいかず、EXPLAINまたはEXPLAIN EXTENDEDヘルプを正確に理解できません。複数の自己結合とインデックスを使って自分の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

間違っている場合は私に知らせてください。 – Jon

+2

あなたがEXPLAINを提供したことは素晴らしいことですが、基本も必要です。参照:[私は非常に単純なSQLクエリと思われるものに対してMCVEを提供するのはなぜですか?](https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve- for-what-like-to-my-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-way自己結合ですが、要素が異なります。これは標準的なテーブルで、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 

私もあなたの提案したアプローチを試みましたが、それは役に立ちませんでした。おそらく、この質問はhttps://codereview.stackexchange.comに適しているのは、ここで少しオフトピックや幅広い思わチェックし、何かが私のクエリで

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' 
) 
関連する問題