优化我的mysql查询

时间:2015-01-29 16:51:21

标签: php 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应用程序中使用此查询,我也尝试过memcache。 请帮助我理解,我如何优化我的查询或者这里有什么问题。

1 个答案:

答案 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"操作。)