继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

全文索引对索引选择的干扰

largeQ
关注TA
已关注
手记 953
粉丝 92
获赞 585


mysql全文索引使用得到,对性能提升有一定帮助;但是,若使用不得到,将会是异常灾难;mysql全文索引对整个优化器的索引选择都有干扰。看我生产环境下优化过的一条sql

SELECT  DISTINCT pc.products_id, pd.products_name,p.products_date_added,pso.products_id 

FROM products_to_categories AS pc

 LEFT JOIN products_description AS pd  ON pd.products_id=pc.products_id

 LEFT JOIN products AS p ON p.products_id=pd.products_id

 LEFT JOIN specials AS sps ON sps.products_id=p.products_id

 LEFT JOIN temp_products_7days_orders_amount AS 7days ON 7days.products_id=pc.products_id

 LEFT JOIN products_realtime_quantity AS prq ON prq.sku_or_poa = p.products_model 

 LEFT JOIN products_stockout AS pso ON pso.products_id=pd.products_id

WHERE  p.products_status=1 AND (prq.msg != 'Temporary out stock.' OR ISNULL(prq.msg)) 

AND pc.categories_id  IN ( 153,323,1055,1241,1431)

AND  MATCH(pd.products_name) AGAINST('*iphone*' IN BOOLEAN MODE) AND  MATCH(pd.products_name)

AGAINST('*c*' IN BOOLEAN MODE) ORDER BY 7days.orders_sum DESC

这条语句执行非常慢,经常出现卡住情况,有时候发现执行需要几分钟,而结果才几条,该语句也为涉及到大结果运算,各种连表条件上上都有索引。唯一特殊的地方就是pd.products_name为全文索引,而且执行的过程中pc.categories_id优先级高于pd.products_name全文索引,导致使用了pc.categories_id索引。按理来讲,这样也没有多大关系。但是explain后发现了问题

+----+-------------+-------+----------+-----------------------+-------------------+---------+---------------------------+------+----------------------------------------------+

| id | select_type | table | type     | possible_keys         | key               | key_len | ref                       | rows | Extra                                        |

+----+-------------+-------+----------+-----------------------+-------------------+---------+---------------------------+------+----------------------------------------------+

|  1 | SIMPLE      | pc    | range    | PRIMARY,categories_id | categories_id     | 4       | NULL                      |  307 | Using where; Using temporary; Using filesort |

|  1 | SIMPLE      | pd    | fulltext | PRIMARY,products_name | products_name     | 0       |                           |    1 | Using where                                  |

|  1 | SIMPLE      | p     | eq_ref   | PRIMARY               | PRIMARY           | 4       | banggood.pd.products_id   |    1 | Using where                                  |

|  1 | SIMPLE      | sps   | ref      | products_id           | products_id       | 4       | banggood.pd.products_id   |   16 | Using index                                  |

|  1 | SIMPLE      | 7days | ref      | PRIMARY               | PRIMARY           | 4       | banggood.p.products_id    | 1032 |                                              |

|  1 | SIMPLE      | prq   | ref      | ix_prg_sku_or_poa     | ix_prg_sku_or_poa | 152     | banggood.p.products_model |   10 | Using where                                  |

|  1 | SIMPLE      | pso   | eq_ref   | PRIMARY               | PRIMARY           | 4       | banggood.pd.products_id   |    1 | Using index                                  |

+----+-------------+-------+----------+-----------------------+-------------------+---------+---------------------------+------+----------------------------------------------+

我们发现驱动表示pc表,使用了categories_id索引,可能优化器优先选择了它,但是再看pd表,

按理来讲,这个时候pd表应该使用products_id索引,也就是这个表的primary key,但是优化器却选择了products_name全文索引,坑爹了!

profiling这条语句,执行时间为2分钟以上

+-------------------------+------------+-----------+------------+--------------+---------------+

| Status                  | Duration   | CPU_user  | CPU_system | Block_ops_in | Block_ops_out |

+-------------------------+------------+-----------+------------+--------------+---------------+

| starting                |   0.000415 |  0.000000 |   0.000000 |            0 |             0 |

| checking permissions    |   0.000011 |  0.000000 |   0.000000 |            0 |             0 |

| checking permissions    |   0.000004 |  0.000000 |   0.000000 |            0 |             0 |

| checking permissions    |   0.000002 |  0.000000 |   0.000000 |            0 |             0 |

| checking permissions    |   0.000003 |  0.000000 |   0.000000 |            0 |             0 |

| checking permissions    |   0.000056 |  0.001000 |   0.000000 |            0 |             0 |

| checking permissions    |   0.000006 |  0.000000 |   0.000000 |            0 |             0 |

| checking permissions    |   0.000009 |  0.000000 |   0.000000 |            0 |             0 |

| Opening tables          |   0.000225 |  0.000000 |   0.000000 |            0 |             0 |

| System lock             |   0.000029 |  0.000000 |   0.000000 |            0 |             0 |

| init                    |   0.000138 |  0.000000 |   0.000000 |            0 |             0 |

| optimizing              |   0.000046 |  0.000000 |   0.000000 |            0 |             0 |

| statistics              |   0.001115 |  0.001000 |   0.000000 |            0 |             0 |

| preparing               |   0.001246 |  0.002000 |   0.000000 |            0 |             0 |

| FULLTEXT initialization |   0.000088 |  0.000000 |   0.000000 |            0 |             0 |

| Creating tmp table      |   0.000057 |  0.000000 |   0.000000 |            0 |             0 |

| executing               |   0.000005 |  0.000000 |   0.000000 |            0 |             0 |

| Copying to tmp table    | 120.430834 | 81.227651 |  38.749110 |         1112 |             0 |

| Sorting result          |   0.000058 |  0.000000 |   0.000000 |            0 |             0 |

| Sending data            |   0.000026 |  0.000000 |   0.000000 |            0 |             0 |

| end                     |   0.000007 |  0.000000 |   0.000000 |            0 |             0 |

| removing tmp table      |   0.000015 |  0.000000 |   0.000000 |            0 |             0 |

| end                     |   0.000041 |  0.001000 |   0.000000 |            0 |             0 |

| query end               |   0.000007 |  0.000000 |   0.000000 |            0 |             0 |

| closing tables          |   0.000023 |  0.000000 |   0.000000 |            0 |             0 |

| freeing items           |   0.008546 |  0.000000 |   0.007999 |            0 |             0 |

| logging slow query      |   0.000008 |  0.000000 |   0.000000 |            0 |             0 |

| logging slow query      |   0.000007 |  0.000000 |   0.000000 |            0 |             0 |

| cleaning up             |   0.000008 |  0.000000 |   0.000000 |            0 |             0 |

+-------------------------+------------+-----------+------------+--------------+---------------+

看到Copying to tmp table占据了大量的cpu运算。

看来,mysql优化器太弱了,又要我们强制使用索引了!force index(primary) ,强制使用pd表的主键

改成如下

SELECT  DISTINCT pc.products_id, pd.products_name,p.products_date_added,pso.products_id 

FROM products_to_categories AS pc

 LEFT JOIN products_description AS pd FORCE INDEX(PRIMARY) ON pd.products_id=pc.products_id

 LEFT JOIN products AS p ON p.products_id=pd.products_id

 LEFT JOIN specials AS sps ON sps.products_id=p.products_id

 LEFT JOIN temp_products_7days_orders_amount AS 7days ON 7days.products_id=pc.products_id

 LEFT JOIN products_realtime_quantity AS prq ON prq.sku_or_poa = p.products_model 

 LEFT JOIN products_stockout AS pso ON pso.products_id=pd.products_id

WHERE  p.products_status=1 AND (prq.msg != 'Temporary out stock.' OR ISNULL(prq.msg)) 

AND pc.categories_id  IN ( 153,323,1055,1241,1431)

AND  MATCH(pd.products_name) AGAINST('*iphone*' IN BOOLEAN MODE) AND  MATCH(pd.products_name)

AGAINST('*c*' IN BOOLEAN MODE) ORDER BY 7days.orders_sum DESC

explain如下

+----+-------------+-------+--------+-----------------------+-------------------+---------+---------------------------+------+----------------------------------------------+

| id | select_type | table | type   | possible_keys         | key               | key_len | ref                       | rows | Extra                                        |

+----+-------------+-------+--------+-----------------------+-------------------+---------+---------------------------+------+----------------------------------------------+

|  1 | SIMPLE      | pc    | range  | PRIMARY,categories_id | categories_id     | 4       | NULL                      |  307 | Using where; Using temporary; Using filesort |

|  1 | SIMPLE      | p     | eq_ref | PRIMARY               | PRIMARY           | 4       | banggood.pc.products_id   |    1 | Using where                                  |

|  1 | SIMPLE      | pd    | ref    | PRIMARY               | PRIMARY           | 4       | banggood.p.products_id    |  764 | Using where                                  |

|  1 | SIMPLE      | sps   | ref    | products_id           | products_id       | 4       | banggood.pc.products_id   |   16 | Using index                                  |

|  1 | SIMPLE      | 7days | ref    | PRIMARY               | PRIMARY           | 4       | banggood.p.products_id    | 1032 |                                              |

|  1 | SIMPLE      | prq   | ref    | ix_prg_sku_or_poa     | ix_prg_sku_or_poa | 152     | banggood.p.products_model |   10 | Using where                                  |

|  1 | SIMPLE      | pso   | eq_ref | PRIMARY               | PRIMARY           | 4       | banggood.pd.products_id   |    1 | Using index                                  |

+----+-------------+-------+--------+-----------------------+-------------------+---------+---------------------------+------+----------------------------------------------+

pd表索引已经使用正确;

profiling如下

+-------------------------+----------+----------+------------+--------------+---------------+

| Status                  | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |

+-------------------------+----------+----------+------------+--------------+---------------+

| starting                | 0.000191 | 0.000000 |   0.000000 |            0 |             0 |

| checking permissions    | 0.000010 | 0.000000 |   0.000000 |            0 |             0 |

| checking permissions    | 0.000003 | 0.000000 |   0.000000 |            0 |             0 |

| checking permissions    | 0.000002 | 0.000000 |   0.000000 |            0 |             0 |

| checking permissions    | 0.000002 | 0.000000 |   0.000000 |            0 |             0 |

| checking permissions    | 0.000003 | 0.000000 |   0.000000 |            0 |             0 |

| checking permissions    | 0.000002 | 0.000000 |   0.000000 |            0 |             0 |

| checking permissions    | 0.000007 | 0.000000 |   0.000000 |            0 |             0 |

| Opening tables          | 0.000184 | 0.000000 |   0.000000 |            0 |             8 |

| System lock             | 0.000021 | 0.000000 |   0.000000 |            0 |             0 |

| init                    | 0.000074 | 0.000000 |   0.000000 |            0 |             0 |

| optimizing              | 0.000034 | 0.000000 |   0.000000 |            0 |             0 |

| statistics              | 0.000191 | 0.000999 |   0.000000 |            0 |             0 |

| preparing               | 0.000052 | 0.000000 |   0.000000 |            0 |             0 |

| FULLTEXT initialization | 0.000019 | 0.000000 |   0.000000 |            0 |             0 |

| Creating tmp table      | 0.000041 | 0.000000 |   0.000000 |            0 |             0 |

| executing               | 0.000005 | 0.000000 |   0.000000 |            0 |             0 |

| Copying to tmp table    | 0.006914 | 0.000000 |   0.005999 |            0 |             0 |

| Sorting result          | 0.000021 | 0.000000 |   0.000000 |            0 |             0 |

| Sending data            | 0.000021 | 0.000000 |   0.000000 |            0 |             0 |

| end                     | 0.000004 | 0.000000 |   0.000000 |            0 |             0 |

| removing tmp table      | 0.000008 | 0.000000 |   0.000000 |            0 |             0 |

| end                     | 0.000004 | 0.000000 |   0.000000 |            0 |             0 |

| query end               | 0.000004 | 0.000000 |   0.000000 |            0 |             0 |

| closing tables          | 0.000020 | 0.000000 |   0.000000 |            0 |             0 |

| freeing items           | 0.000100 | 0.000000 |   0.001000 |            0 |             0 |

| logging slow query      | 0.000006 | 0.000000 |   0.000000 |            0 |             0 |

| cleaning up             | 0.000006 | 0.000000 |   0.000000 |            0 |             0 |

+-------------------------+----------+----------+------------+--------------+---------------+

执行时间已经下降为0.01以下!可以看到Creating tmp table性能损耗选项已经不见!

注意事项:

使用全文索引时,如果全文索引不能为驱动索引,那么会导致mysql优化器在选择其他索引为驱动索引的同时,对全文索引所在表的索引选择出现错误的判断,个人认为这个问题可以视为一个bug。

©著作权归作者所有:来自51CTO博客作者justforqdj的原创作品,如需转载,请注明出处,否则将追究法律责任

mysql fulltextmysql fulltext indexmysql 全文索引使用mysql sql调优记录


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP