当MySQL优化器选择不在一个小的连接表上使用键时,如何避免全表扫描
我遇到了一个奇怪的问题,我不知道如何正确地搜索这个场景。我在下面提供了两个表格:当MySQL优化器选择不在一个小的连接表上使用键时,如何避免全表扫描,mysql,query-optimization,Mysql,Query Optimization,我遇到了一个奇怪的问题,我不知道如何正确地搜索这个场景。我在下面提供了两个表格: CREATE TABLE revenue_centers ( revc_id int(11) NOT NULL AUTO_INCREMENT, revc_name varchar(50) COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (revc_id) ) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8 C
CREATE TABLE revenue_centers (
revc_id int(11) NOT NULL AUTO_INCREMENT,
revc_name varchar(50) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (revc_id)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE cpt (
cpt_id int(11) NOT NULL AUTO_INCREMENT,
cpt_revc_id int(11) NOT NULL,
PRIMARY KEY (cpt_id),
KEY cpt_revc_id (cpt_revc_id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
有更多的列,但上面的列是所有需要的。这些表跨多个客户的独立数据库复制。以下是我提出的问题之一:
select*from cpt left join revenue\u centers on cpt\u revc\u id=revc\u id order by cpt\u id代码>
使用EXPLAIN,在收入中心中至少有4行的表上,我们得到以下结果:
1 SIMPLE cpt index PRIMARY 4 89664
1 SIMPLE revenue_centers eq_ref PRIMARY PRIMARY 4 _8.cpt.cpt_revc_id 1
1 SIMPLE cpt ALL 22725 Using temporary; Using filesort
1 SIMPLE revenue_centers ALL PRIMARY 1 Using where; Using join buffer (Block Nested Loop)
查询速度快,没有延迟。对于不使用收入中心的客户,我们提供以下服务:
1 SIMPLE cpt index PRIMARY 4 89664
1 SIMPLE revenue_centers eq_ref PRIMARY PRIMARY 4 _8.cpt.cpt_revc_id 1
1 SIMPLE cpt ALL 22725 Using temporary; Using filesort
1 SIMPLE revenue_centers ALL PRIMARY 1 Using where; Using join buffer (Block Nested Loop)
我理解,因为对收入中心的完全扫描可能比索引1便宜,mysql选择使用连接缓冲区。我不明白为什么它选择在cpt表上进行完全扫描
如果我在连接上使用FORCE INDEX提示,它将变成eq_ref类型的连接,cpt查询不再使用临时表或filesort。如果可能的话,我希望避免将其添加到我们的代码中。我尝试将max_seeks_for_key设置为低至1,以查看是否可以强制优化器在没有索引提示的情况下使用主键,但它拒绝更改
除了将强制索引添加到我们的代码库之外,还有什么方法可以改进此查询或至少防止使用临时表吗?@bill karwin感谢您提供的格式帮助。ORDER BY
优化需要多列索引。它在MySQL手册中。。因此,您需要创建索引cpt(cpt\u revc\u id,cpt\u id)
,以避免“使用临时;使用文件排序”,您的意思是,在慢速情况下,收入中心中没有行
。。。每个查询需要多长时间?@RaymondNijland-因为这是InnoDB,这实际上就是索引中包含的内容。