如何在MySQL中设置正确的索引或编写正确的查询?

如何在MySQL中设置正确的索引或编写正确的查询?,mysql,indexing,left-join,Mysql,Indexing,Left Join,我有一个表,表上有唯一的索引(col1,col2,col3) 我有一个关于这张桌子的问题 ... left join my_table t on t.col1=x.col1 and t.col2=x.col2 and t.col3 in (1,2,3) 当col3的列表只有一个项目时,解释显示一个eq\u ref连接 +----+-------------+----------+------------+--------+---------------+-----+---------+----

我有一个表,表上有唯一的索引(col1,col2,col3)

我有一个关于这张桌子的问题

...
left join my_table t on t.col1=x.col1 and t.col2=x.col2 and t.col3 in (1,2,3)
当col3的列表只有一个项目时,解释显示一个
eq\u ref连接

+----+-------------+----------+------------+--------+---------------+-----+---------+---------------------+------+----------+-------+
| id | select_type |  table   | partitions |  type  | possible_keys | key | key_len |         ref         | rows | filtered | Extra |
+----+-------------+----------+------------+--------+---------------+-----+---------+---------------------+------+----------+-------+
|  1 | PRIMARY     | my_table | NULL       | eq_ref | veh           | veh |       8 | x.col1,x.col2,const |    1 |   100.00 | NULL  |
+----+-------------+----------+------------+--------+---------------+-----+---------+---------------------+------+----------+-------+
但对于两个或多个项目,不再使用索引

+----+-------------+----------+------------+------+---------------+------+---------+------+----------+----------+------------------------------------------------+
| id | select_type |  table   | partitions | type | possible_keys | key  | key_len | ref  |   rows   | filtered |                     Extra                      |
+----+-------------+----------+------------+------+---------------+------+---------+------+----------+----------+------------------------------------------------+
|  1 | PRIMARY     | my_table | NULL       | ALL  | veh           | NULL | NULL    | NULL | 13705314 |   100.00 | Range checked for each record (index map: 0x3) |
+----+-------------+----------+------------+------+---------------+------+---------+------+----------+----------+------------------------------------------------+
col3上的附加非唯一索引没有帮助
如何设置可由此类
连接使用的索引

或者如何重写查询


编辑:附加信息

  • 使用InnoDB,而不是MyISAM或内存。大多数优化器的改进只涉及InnoDB。(警告:我没有证据证明这会有所帮助。)

  • 进行更改时,将唯一键更改为
    主键(col1、col2、col3)
    。InnoDB PK的“集群”性质应该会有进一步的帮助。(此更改对MyISAM没有影响。)


  • 什么版本的MySQL?(优化器已经做了改进;不知道是否有任何改进可以帮助您的特定情况。)版本是5.7.19Hmm。。。让我们看看问题中附加的
    EXPLAIN FORMAT=JSON SELECT…
    以及
    SHOW CREATE TABLEs
    请求的信息
    explain format=json
    select x.*,ifnull(group_concat(t.col4 separator ','),'') col4
    from
      (select col1,col2,total from tmp_data limit 10) x
      left join my_table t on t.col1=x.col1 and t.col2=x.col2 and t.col3 in (38,85)
    group by x.col1,x.col2
    order by x.total desc
    
    {
     "query_block": {
       "select_id": 1,
       "cost_info": {
         "query_cost": "411271.71"
       },
       "ordering_operation": {
         "using_temporary_table": true,
         "using_filesort": true,
         "grouping_operation": {
           "using_filesort": true,
           "nested_loop": [
             {
               "table": {
                 "table_name": "x",
                 "access_type": "ALL",
                 "rows_examined_per_scan": 10,
                 "rows_produced_per_join": 10,
                 "filtered": "100.00",
                 "cost_info": {
                   "read_cost": "10.50",
                   "eval_cost": "2.00",
                   "prefix_cost": "12.50",
                   "data_read_per_join": "240"
                 },
                 "used_columns": [
                   "col1",
                   "col2",
                   "total"
                 ],
                 "materialized_from_subquery": {
                   "using_temporary_table": true,
                   "dependent": false,
                   "cacheable": true,
                   "query_block": {
                     "select_id": 2,
                     "cost_info": {
                       "query_cost": "12.50"
                     },
                     "table": {
                       "table_name": "tmp_data",
                       "access_type": "ALL",
                       "rows_examined_per_scan": 10,
                       "rows_produced_per_join": 10,
                       "filtered": "100.00",
                       "cost_info": {
                         "read_cost": "10.50",
                         "eval_cost": "2.00",
                         "prefix_cost": "12.50",
                         "data_read_per_join": "5K"
                       },
                       "used_columns": [
                         "col1",
                         "col2",
                         "total"
                       ]
                     }
                   }
                 }
               }
             },
             {
               "table": {
                 "table_name": "t",
                 "access_type": "ALL",
                 "possible_keys": [
                   "veh",
                   "col3"
                 ],
                 "rows_examined_per_scan": 13705314,
                 "rows_produced_per_join": 320380,
                 "filtered": "100.00",
                 "range_checked_for_each_record": "index map: 0x3",
                 "cost_info": {
                   "read_cost": "347183.21",
                   "eval_cost": "64076.00",
                   "prefix_cost": "411271.71",
                   "data_read_per_join": "7M"
                 },
                 "used_columns": [
                   "col1",
                   "col2",
                   "col3",
                   "col4"
                 ]
               }
             }
           ]
         }
       }
     }
    }
    
    create table tmp_data 
    (col1 mediumint(1) unsigned not null default 0,
     col2 mediumint(1) unsigned not null,
     total decimal(11,0) not null default 0,
     key veh (col1,col2) using hash
    ) engine=memory default charset=latin1 collate=latin1_general_ci
    
    create table my_table
    (col1 mediumint(1) unsigned not null,
     col2 mediumint(1) unsigned not null,
     col3 smallint(1) unsigned not null,
     col4 text collate latin1_general_ci,
     unique key veh (col1,col2,col3),
     key col3 (col3)
    ) engine=myisam default charset=latin1 collate=latin1_general_ci