我清楚地知道有很多关于这个主题的问题,但我无法优化我的问题。 以下是我的询问:
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应用程序中使用此查询,我也尝试过memcache。 请帮助我理解,我如何优化我的查询或者这里有什么问题。
答案 0 :(得分:0)
在students_placements
表格中添加适当的索引(在查询中别名为sp
)。
CREATE INDEX student_placements_IX1
ON student_placements (batch_id, student_id)
EXPLAIN输出显示该表的完整扫描(" ALL")。使用该索引,我们期望EXPLAIN输出显示ref
操作。
此外,在batches
表(在查询中别名为b
)添加如下索引:
CREATE INDEX batches_IX1
ON batches (training_center_id, id, starttime, endtime)
如果表的查询中引用的所有列都来自索引,则索引称为"覆盖索引"对于查询,EXPLAIN
输出将显示"使用索引"在Extra列中。
如果id
表中的training_centers
是唯一的或PRIMARY KEY(在questy中别名为tc
),您可能还会考虑更改查询来执行此操作:
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可以使用索引来避免"使用filesort"操作。)