MySQL在复杂情况下可以做的一些优化

昨天,对复杂相关SQL的优化进行了讨论。这种SQL的优化通常考虑到以下四点:

第一.查询返回的结果集,通常是查询返回的结果集很少,有信心优化它;

其次,驾驶台的选择是非常重要的。通过查看执行计划,我们可以看到优化器选择的驱动表可以从执行计划中的行中一般地反映问题。

第三。明确表之间的关系,注意是否有相关字段的适当索引。

第四。我们可以很方便的利用straight_join关键词执行表之间的关联的序列验证某些猜想。

SQL:

执行时间:




MySQL >选择c.yh_id,
-> c.yh_dm,
-> c.yh_mc,
->立方毫米,
-> c.yh_lx,
-> a.jg_id,
-> a.jg_dm,
-> a.jg_mc,
-> a.jgxz_dm,
d.js_dm -> yh_js
从B到A。
加入D ->左d.yh_id = c.yh_id
->在a.jg_id = b.jg_id
->和b.yh_id = c.yh_id
a.yx_bj =Y>和
c.sc_bj =N- >和
c.yx_bj =Y>和
c.sc_bj =N- >和
->和c.yh_dm = '006939748xx;

1行集(0.75秒)




SQL查询实际上只返回一行数据,但是可以750ms查看执行计划:


MySQL >解释
选择-> c.yh_id,
-> c.yh_dm,
-> c.yh_mc,
->立方毫米,
-> c.yh_lx,
-> a.jg_id,
-> a.jg_dm,
-> a.jg_mc,
-> a.jgxz_dm,
d.js_dm -> yh_js
从B到A。
加入D ->左d.yh_id = c.yh_id
->在a.jg_id = b.jg_id
->和b.yh_id = c.yh_id
a.yx_bj =Y>和
c.sc_bj =N- >和
c.yx_bj =Y>和
c.sc_bj =N- >和
->和c.yh_dm = '006939748xx;

+ + + - + + + + + +————————
我select_type表| | | |型possible_keys关键key_len | | | | REF |行|额外|
+ + + - + + + + + +————————
| 1 |简单|一| |所有小学、index_jg空空空| | | | 52616 |使用|
| 1 |简单| B参考初级| | | | 98 | test.a.jg_id | 1 |使用索引|
| 1 |简单| C eq_ref初级| | | | 98 | test.b.yh_id | 1 |使用|
| 1 |简单| D指数空主| | | | 196 |空| 54584 |使用索引|
+ + + - + + + + + +————————




您可以在执行计划中看到两个更突出的性能瓶颈:


| 1 |简单|一| |所有小学、index_jg空空空| | | | 52616 |使用|

| 1 |简单| D指数空主| | | | 196 |空| 54584 |使用索引|




因为D是一个左连接表,所以表驱动器不会选择D表,我们来看看A,B,C三大小:


从C中选择计数(*);
+——+
|计数(*)|
+——+
53731 | |
+——+

从一个;
+——+
|计数(*)|
+——+
53335 | |
+——+

从b中选择计数(*);
+——+
|计数(*)|
+——+
105809 | |
+——+




因为B表中的数据量比其他两个表大,而且B表上没有查询过滤条件,所以驱动程序表很可能选择B。

选择一个实用的优化器作为驱动表,为什么C表不作为驱动表呢让我们来分析一下。

第一阶段:作为驾驶台

- > B C D u2013 > >:

(1):a.jg_id = b.jg_id ->(B指数:主键(` jg_id `,` yh_id `))

(2):b.yh_id = c.yh_id ->(C指数:主键(` yh_id `))

(3):c.yh_id = d.yh_id ->(D指数:主键(` js_dm `,` yh_id `))

因为在D表没有yh_id指数,指数增加指数D表:




改变表添加索引ind_yh_id(yh_id);



实施计划:




+ + + - + + + + + + +—
我select_type表| | | |型possible_keys关键key_len | | | | REF |行|额外|
+ + + - + + + + + + +—
| 1 |简单|一| |所有小学、index_jg空空空| | | | 52616 |使用|
| 1 |简单| B参考初级| | | | 98 | test.a.jg_id | 1 |使用索引|
| 1 |简单| C eq_ref初级| | | | 98 | test.b.yh_id | 1 |使用|
| 1 |简单| D裁判ind_yh_id ind_yh_id | | | | 98 | test.b.yh_id | 272 |使用索引|
+ + + - + + + + + + +—



执行时间:




1行集(0.77秒)



在d表上添加索引后,d表的扫描行数下降到272行(第一:54584)。


| 1 |简单| D裁判ind_yh_id ind_yh_id | | | | 98 | test.b.yh_id | 272 |使用索引|




第二阶段:C表用作驱动程序表。

D

^

|

C—B - A

因为有一个高的C表yh_dm过滤条件,我们创建了一个在yh_dm指数:




MySQL > select count(*)从C,yh_dm = '006939748xx;
+——+
|计数(*)|
+——+
2 | |
+——+



添加索引:




修改表C添加索引ind_yh_dm(yh_dm)



看执行计划:




+ + + - - + + + + + + +———————
我select_type表| | | |型possible_keys关键key_len | | | | REF |行|额外|
+ + + - - + + + + + + +———————
| 1 |简单|一| |所有小学、index_jg空空空| | | | 52616 |使用|
| 1 |简单| B参考初级| | | | 98 | test.a.jg_id | 1 |使用索引|
| 1 |简单| C | | eq_ref小学,ind_yh_dm初级| | 98 | test.b.yh_id | 1 |使用|
| 1 |简单| D裁判ind_yh_id ind_yh_id | | | | 98 | test.b.yh_id | 272 |使用索引|
+ + + - - + + + + + + +———————



执行时间:




1行集(0.74秒)



在C表上添加一个索引,索引仍然没有进行,或者作为驱动表的计划,所以我们在这里来分析为什么或作为一个驱动程序表

1):c.yh_id = b.yh_id ->(主键(` jg_id `,` yh_id `))

如果C表为驱动表,C表和B在相关的时间表,因为在B表B表索引没有yh_id领域,由于数据量大,因此,如果C优化器在驾驶台,它将与B表密切相关(从在这里,你可以用straight_join为驱动力的C表的使用);

如果一个表是由B.和B的带动下,在相关的时间表,因为在指数的B表的jg_id领域,使优化器使用作为驱动表价格低于C驱动板价格;

所以,如果我们想用C表作为驱动表,我们只需要在B添加的yh_id指数:




修改表添加索引ind_yh_id(yh_id)B;



2):b.jg_id = a.jg_id ->(主键(` jg_id `))

3):c.yh_id = d.yh_id ->(关键` ind_yh_id `(` yh_id `))

实施计划:




+++—
我select_type表| | | |型possible_keys关键key_len | | | | REF |行|额外|
+++—
| 1 |简单| C | |参考小学,ind_yh_dm ind_yh_dm | | 57 | const | 2 |使用|
| 1 |简单| D裁判ind_yh_id ind_yh_id | | | | 98 | test.c.yh_id | 272 |使用索引|
| 1 |简单| B | |参考小学,ind_yh_id ind_yh_id | | 98 | test.c.yh_id | 531 |使用索引|
| 1 |简单|一| | eq_ref小学,index_jg初级| | 98 | test.b.jg_id | 1 |使用|
+++—



执行时间:




1行集(0秒)



可以看出,在执行计划的行已大大减少,并且执行时间也从原来的750ms降低到0毫秒的水平。