我遇到了一个奇怪的问题,我不确定如何正确搜索该方案。我在下面提供了2张桌子:
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_centers on cpt_revc_id=revc_id order by cpt_id;
使用EXPLAIN,在Revenue_centers中至少有4行的表上,我们得到以下信息:
1 SIMPLE cpt index PRIMARY 4 89664
1 SIMPLE revenue_centers eq_ref PRIMARY PRIMARY 4 _8.cpt.cpt_revc_id 1
查询很快,没有延迟。对于不使用Revenue_centers的客户,我们得到以下信息:
1 SIMPLE cpt ALL 22725 Using temporary; Using filesort
1 SIMPLE revenue_centers ALL PRIMARY 1 Using where; Using join buffer (Block Nested Loop)
我了解到,由于对Revenue_centers进行全面扫描可能比通过索引1便宜,因此mysql选择使用连接缓冲区。我不明白为什么它选择对cpt表进行完全扫描。
如果在联接上使用FORCE INDEX提示,它将变为eq_ref类型的联接,并且cpt查询不再使用临时表或文件排序。如果可能的话,我想避免将此添加到我们的代码中。我试图将max_seeks_for_key设置为低至1,以查看是否可以强制优化器使用没有索引提示的主键,但是它拒绝更改。
除了将FORCE INDEX添加到我们的代码库外,还有什么方法可以改善此查询或至少阻止使用临时表?