2015-01-29 5 views
0

Я четко знаю, что есть много вопросов, уже заданных по этой теме, но я не мог оптимизировать мой. Так ниже мой запрос:Оптимизация моего запроса mysql

 
    select tc.id, tc.name tc, s.name state, d.name district, 
    count(distinct case when curdate() between b.starttime and b.endtime then b.id end) as active, 
    (case when count(distinct case when curdate() between b.starttime and b.endtime then b.id end) > 0 then 'active' when tc.status = 'Archived-I' then 'transitioned' when count(distinct case when curdate() between b.starttime and b.endtime then b.id end) = 0 and tc.status != 'Archived-I' then 'Idle' end) as _status, 
    count(distinct(b.id)) as batches, sum(case when sb.status = 'active' then 1 else 0 end) as in_training, count(distinct case when sb.status = 'complete' then sb.student_id end) as trained, 
    count(distinct(sa.student_id)) as assessed, count(distinct(sp.student_id)) as placed 
    from training_centers tc left join batches b on b.training_center_id = tc.id 
    left join student_batches sb on b.id = sb.batch_id 
    left join student_assessments sa on sa.batch_id = b.id 
    left join student_placements sp on sp.batch_id = b.id 
    left join states s on s.id = tc.state_id 
    left join districts d on d.id = tc.district_id 
    where tc.implementing_agency_id = 28 
    group by tc.id 
    order by tc.name 

Вывод EXPLAIN ниже:

 
    id|select_type|table|type|possible_keys|key|key_len|ref|rows|Extra 
    1|SIMPLE|tc|ref|implementing agency|implementing agency|4|const|201|Using temporary; Using filesort 
    1|SIMPLE|b|ALL|NULL|NULL|NULL|NULL|11018| 
    1|SIMPLE|sb|ref|batch id|batch id|4|ministry_mis.b.id|10| 
    1|SIMPLE|sa|ref|batch|batch|4|ministry_mis.b.id|7| 
    1|SIMPLE|sp|ALL|NULL|NULL|NULL|NULL|78799| 
    1|SIMPLE|s|eq_ref|PRIMARY|PRIMARY|4|ministry_mis.tc.state_id|1| 
    1|SIMPLE|d|eq_ref|PRIMARY|PRIMARY|4|ministry_mis.tc.district_id|1|1| 

Я уже пробовал кэширование запросов и так как я использую этот запрос в приложении PHP, я попытался кэша памяти, как Что ж. Пожалуйста, помогите мне понять, как я могу оптимизировать свой запрос или что-то здесь не так.

+0

Использование 'group by' и' order by' почти всегда является проблемой. В вашем объяснении показано использование временного; Использование filesort, которое всегда медленное. –

+0

Вы можете попытаться установить temp dir для MySQL в/dev/shm (который обычно монтируется tmpfs), поэтому все операции с файловой системой, вызванные «использованием временных», будут находиться в памяти, а не в файле на диске. –

ответ

0

Добавить подходящий индекс в таблицу students_placements (с псевдонимом sp в запросе).

CREATE INDEX student_placements_IX1 
    ON student_placements (batch_id, student_id) 

Выход EXPLAIN показывает полное сканирование этой таблицы («ВСЕ»). С этим индексом мы ожидаем, что вывод EXPLAIN отобразит операцию ref.

Кроме того, на batches столе (псевдонимы, как b в запросе) добавить индекс, как:

CREATE INDEX batches_IX1 
    ON batches (training_center_id, id, starttime, endtime) 

Если все столбцы, упоминаемые в запросе для таблицы приходит из индекса, индекс называемый «индекс покрытия» для запроса, а выход EXPLAIN будет показывать «Использование индекса» в столбце «Дополнительно».

Если id является UNIQUE или PRIMARY KEY на training_centers столе (с псевдонимом tc в questy), вы можете также рассмотреть вопрос об изменении запроса, чтобы сделать это:

GROUP BY tc.name, tc.id 
ORDER BY tc.name 

Индекс покрытия на training_centers, может также быть полезным:

CREATE INDEX training_centers_IX1 
    ON training_centers (implementing_agency_id, name, id, state_id, district_id, status) 

Мы должны были бы смотреть на EXPLAIN после добавления индексов, и идти оттуда. (Иногда MySQL может использовать индекс, чтобы избежать операции «Использование файловой системы», если имеется соответствующий индекс.)

+0

Спасибо. Теперь мой запрос занимает гораздо меньше времени по сравнению с тем, что он принимал ранее. Но он все еще не настолько хорош, поэтому вы можете предложить мне другие вещи, которые я могу сделать, чтобы ускорить запрос больше? – Raakesh

+0

Теперь я знаю, почему мой оператор EXPLAIN показывал использование временного и использования Filesort. Итак, вот ссылка [link] (http://dev.mysql.com/doc/refman/5.5/en/internal-temporary-tables.html) для людей, которые застряли как я. – Raakesh

Смежные вопросы