Mysql查询优化——范围搜索

Posted

技术标签:

【中文标题】Mysql查询优化——范围搜索【英文标题】:Mysql query optimisation - range searches 【发布时间】:2013-09-12 11:45:15 【问题描述】:

希望找到一些关于如何优化此查询的想法 - 多次范围搜索非常尴尬

SELECT t1.id, t1.custom_track_id, t1.deleted, t1.last_modified, t1.client_id
FROM tracks t1
INNER JOIN tracks t2 ON t1.custom_track_id = t2.custom_track_id
AND t1.last_modified > t2.last_modified
AND t1.deleted !=0
AND t2.deleted =0
AND t2.client_id
IN ( 103, 115, 116 ) 
WHERE t1.client_id
IN ( 103, 115, 116 ) 

它要查找和加入的所有字段都是 INT 字段。

索引(是的,那里有一些狡猾的):

+--------+------------+------------------------------------------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name                                       | Seq_in_index | Column_name                | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+------------------------------------------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tracks |          0 | PRIMARY                                        |            1 | id                         | A         |      566045 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | client_id                                      |            1 | client_id                  | A         |         589 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | featured                                       |            1 | featured                   | A         |          16 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | system_status                                  |            1 | system_status              | A         |          20 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | created_by                                     |            1 | created_by                 | A         |         225 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | custom_track_id                                |            1 | custom_track_id            | A         |      283022 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | custom_track_id                                |            2 | custom_artist_id           | A         |      283022 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | counterpoint_id                                |            1 | counterpoint_id            | A         |      113209 |     NULL | NULL   | YES  | BTREE      |         |               |
| tracks |          1 | system_status_2                                |            1 | system_status              | A         |          20 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | composition                                    |            1 | composition                | A         |          13 |     NULL | NULL   | YES  | BTREE      |         |               |
| tracks |          1 | published_start_date                           |            1 | published_start_date       | A         |          13 |     NULL | NULL   | YES  | BTREE      |         |               |
| tracks |          1 | published_end_date                             |            1 | published_end_date         | A         |          13 |     NULL | NULL   | YES  | BTREE      |         |               |
| tracks |          1 | deleted                                        |            1 | deleted                    | A         |          20 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | restricted_access_required                     |            1 | restricted_access_required | A         |          13 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_deleted_featured_restrictedaccess  |            1 | client_id                  | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_deleted_featured_restrictedaccess  |            2 | custom_track_id            | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_deleted_featured_restrictedaccess  |            3 | deleted                    | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_deleted_featured_restrictedaccess  |            4 | last_modified              | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_customtrackid_deleted_lastmodified |            1 | client_id                  | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_customtrackid_deleted_lastmodified |            2 | custom_track_id            | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_customtrackid_deleted_lastmodified |            3 | deleted                    | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
| tracks |          1 | mv_clientid_customtrackid_deleted_lastmodified |            4 | last_modified              | A         |         336 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+------------------------------------------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

还有解释:

---+---------+-------------------------------------------------+-------+--------------------------+
| id | select_type | table | type  | possible_keys                                                                                                                  | key                                           | key_len | ref                                             | rows  | Extra                    |
+----+-------------+-------+-------+--------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+-------------------------------------------------+-------+--------------------------+
|  1 | SIMPLE      | t1    | range | client_id,custom_track_id,deleted,mv_clientid_deleted_featured_restrictedaccess,mv_clientid_customtrackid_deleted_lastmodified | mv_clientid_deleted_featured_restrictedaccess | 4       | NULL                                            | 16018 | Using where; Using index |
|  1 | SIMPLE      | t2    | ref   | client_id,custom_track_id,deleted,mv_clientid_deleted_featured_restrictedaccess,mv_clientid_customtrackid_deleted_lastmodified | custom_track_id                               | 302     | synchtank_shared_application.t1.custom_track_id |     2 | Using where              |
+----+-------------+-------+-------+--------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+-------------------------------------------------+-------+--------------------------+

因此寻找优化查询或索引的方法。我也很好奇为什么它可以匹配的 2 个复合索引,它选择没有 last_modified 的那个。

为斯蒂芬解释:

+----+-------------+-------+-------+-----------------------------------------------+-----------------------------------------------+---------+------+-------+---------------------------------------------+
| id | select_type | table | type  | possible_keys                                 | key                                           | key_len | ref  | rows  | Extra                                       |
+----+-------------+-------+-------+-----------------------------------------------+-----------------------------------------------+---------+------+-------+---------------------------------------------+
|  1 | SIMPLE      | t1    | range | client_id                                     | client_id                                     | 4       | NULL |  8111 | Using where                                 |
|  1 | SIMPLE      | t2    | range | mv_clientid_deleted_featured_restrictedaccess | mv_clientid_deleted_featured_restrictedaccess | 4       | NULL | 16018 | Using where; Using index; Using join buffer |
+----+-------------+-------+-------+-----------------------------------------------+-----------------------------------------------+---------+------+-------+---------------------------------------------+

【问题讨论】:

deleted 字段包含哪些值? 0 或时间戳整数 【参考方案1】:

你可以尝试强制mysql使用索引:

SELECT 
    t1.id, 
    t1.custom_track_id, 
    t1.deleted, 
    t1.last_modified, 
    t1.client_id
FROM 
    tracks t1 FORCE INDEX(`client_id`)
INNER JOIN tracks t2 FORCE INDEX(`mv_clientid_deleted_featured_restrictedaccess`)
    ON t1.custom_track_id = t2.custom_track_id
    AND t1.last_modified > t2.last_modified 
    AND t2.deleted = 0
    AND t2.client_id IN ( 103, 115, 116 ) 
WHERE 
    t1.client_id IN ( 103, 115, 116 ) 
    AND t1.deleted !=0

通常 mysql 不使用最有效索引的原因是由于基数中的错误统计信息,这就是为什么在具有大量列和索引的大表上运行 OPTIMIZE TABLE 是一种好习惯。

【讨论】:

很高兴知道 - 谢谢。将安排在优化中。我真的不想强制它使用什么索引 @DougMcK 至少在上面运行EXPLAIN 所以看看查询计划可能会更好 解释在上面。 @DougMcK 我的意思是我发布的查询的解释 道歉 - 添加了这一点。看起来该查询比原来的查询更糟糕,现在两者都使用范围搜索

以上是关于Mysql查询优化——范围搜索的主要内容,如果未能解决你的问题,请参考以下文章

MySQL索引原理和慢查询优化

优化 MySQL 全文搜索查询?

Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析

MySQL: 范围查询优化

MySQL物理查询优化技术---index dive辨析

优化 mysql 查询以减少搜索的行数