Optimizing my mysql query
I clearly know that there are plenty of questions already asked on this topic but i couldn't optimize mine. So below is my query:
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
Output of EXPLAIN is below:
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|
I have already tried query caching and since i am using this query in a php application, i have tried memcache as well. Please help me understand, how can i optimize my query or if something is wrong here.
Add an appropriate index on the students_placements
table (aliased as sp
in the query).
CREATE INDEX student_placements_IX1
ON student_placements (batch_id, student_id)
The EXPLAIN output is showing a full scan of that table, ("ALL"). With that index, we'd expect the EXPLAIN output to show a ref
operation.
Also, on the batches
table (aliased as b
in the query) add an index like:
CREATE INDEX batches_IX1
ON batches (training_center_id, id, starttime, endtime)
If all of the columns referenced in the query for a table come from the index, the index is called a "covering index" for the query, and the the EXPLAIN
output will show "Using index" in the Extra column.
If id
is a UNIQUE or PRIMARY KEY on the training_centers
table (aliased as tc
in the questy), you might also consider changing the query to do this:
GROUP BY tc.name, tc.id
ORDER BY tc.name
A covering index on training_centers
, may also be of benefit:
CREATE INDEX training_centers_IX1
ON training_centers (implementing_agency_id, name, id, state_id, district_id, status)
We'd need to look at the EXPLAIN after the indexes are added, and go from there. (Sometimes, MySQL can make use of an index to avoid a "Using filesort" operation, if an appropriate index is available.)
链接地址: http://www.djcxy.com/p/62456.html上一篇: 使用子查询查询MYSQL中的查询优化?
下一篇: 优化我的mysql查询