left join用不到index

问题遇到的现象和发生背景
2个表 vipcard_ar_master ,vipcard
CREATE TABLE vipcard_ar_master (
accnt varchar(20) COLLATE utf8_bin NOT NULL,
hotelid varchar(7) COLLATE utf8_bin NOT NULL,
sign int(11) DEFAULT NULL,
name varchar(100) COLLATE utf8_bin NOT NULL,
sta varchar(1) COLLATE utf8_bin NOT NULL,
artag1 varchar(5) COLLATE utf8_bin DEFAULT NULL,
artag2 varchar(5) COLLATE utf8_bin DEFAULT NULL,
applname varchar(100) COLLATE utf8_bin DEFAULT NULL,
applunit varchar(100) COLLATE utf8_bin DEFAULT NULL,
mobile varchar(20) COLLATE utf8_bin DEFAULT NULL,
phone varchar(20) COLLATE utf8_bin DEFAULT NULL,
email varchar(100) COLLATE utf8_bin DEFAULT NULL,
fax varchar(20) COLLATE utf8_bin DEFAULT NULL,
address1 varchar(250) COLLATE utf8_bin DEFAULT NULL,
address2 varchar(250) COLLATE utf8_bin DEFAULT NULL,
brandids varchar(255) COLLATE utf8_bin DEFAULT NULL,
hotels varchar(1000) COLLATE utf8_bin DEFAULT NULL,
memo varchar(1000) COLLATE utf8_bin DEFAULT NULL,
charge decimal(19,4) NOT NULL,
credit decimal(19,4) NOT NULL,
charge0 decimal(19,4) NOT NULL,
credit0 decimal(19,4) NOT NULL,
credit1 decimal(19,4) DEFAULT NULL,
charge1 decimal(19,4) DEFAULT NULL,
vipcard_limite decimal(19,4) NOT NULL,
accredit decimal(19,4) NOT NULL,
arr date NOT NULL,
dep date NOT NULL,
cby varchar(10) COLLATE utf8_bin NOT NULL,
changed datetime DEFAULT NULL,
chargeby varchar(10) COLLATE utf8_bin DEFAULT NULL,
chargetime datetime DEFAULT NULL,
creditby varchar(10) COLLATE utf8_bin DEFAULT NULL,
credittime datetime DEFAULT NULL,
logmark int(11) NOT NULL,
PRIMARY KEY (hotelid,accnt)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

CREATE TABLE vipcard (
id varchar(20) COLLATE utf8_bin NOT NULL,
hotelid varchar(7) COLLATE utf8_bin NOT NULL,
sign int(11) DEFAULT NULL,
no varchar(20) COLLATE utf8_bin NOT NULL,
sno varchar(20) COLLATE utf8_bin DEFAULT NULL,
mno varchar(20) COLLATE utf8_bin DEFAULT NULL,
mid varchar(20) COLLATE utf8_bin DEFAULT NULL,
sta varchar(1) COLLATE utf8_bin NOT NULL,
type varchar(10) COLLATE utf8_bin NOT NULL,
card_class varchar(10) COLLATE utf8_bin NOT NULL,
src varchar(3) COLLATE utf8_bin NOT NULL,
issue_source varchar(20) COLLATE utf8_bin DEFAULT NULL,
channel varchar(10) COLLATE utf8_bin DEFAULT NULL,
fixed varchar(1) COLLATE utf8_bin DEFAULT NULL,
name varchar(100) COLLATE utf8_bin DEFAULT NULL,
rmratecode varchar(20) COLLATE utf8_bin DEFAULT NULL,
posmode varchar(24) COLLATE utf8_bin DEFAULT NULL,
code3 varchar(30) COLLATE utf8_bin DEFAULT NULL,
code4 varchar(30) COLLATE utf8_bin DEFAULT NULL,
code5 varchar(30) COLLATE utf8_bin DEFAULT NULL,
araccnt1 varchar(20) COLLATE utf8_bin DEFAULT NULL,
pointaccnt varchar(20) COLLATE utf8_bin DEFAULT NULL,
ticketaccnt varchar(20) COLLATE utf8_bin DEFAULT NULL,
kno varchar(15) COLLATE utf8_bin DEFAULT NULL,
cno varchar(15) COLLATE utf8_bin DEFAULT NULL,
hno varchar(15) COLLATE utf8_bin DEFAULT NULL,
arr datetime DEFAULT NULL,
dep datetime DEFAULT NULL,
pwd varchar(10) COLLATE utf8_bin DEFAULT NULL,
checkpwd varchar(1) COLLATE utf8_bin DEFAULT NULL,
share varchar(1) COLLATE utf8_bin DEFAULT NULL,
pwd_q varchar(30) COLLATE utf8_bin DEFAULT NULL,
pwd_a varchar(30) COLLATE utf8_bin DEFAULT NULL,
crc varchar(20) COLLATE utf8_bin DEFAULT NULL,
flag varchar(40) COLLATE utf8_bin NOT NULL,
vipcard_limite decimal(19,4) NOT NULL,
charge decimal(19,4) NOT NULL,
credit decimal(19,4) NOT NULL,
lastnumb int(11) DEFAULT NULL,
card_hotelid varchar(20) COLLATE utf8_bin NOT NULL,
saleid varchar(50) COLLATE utf8_bin DEFAULT NULL,
invite_code varchar(20) COLLATE utf8_bin DEFAULT NULL,
iscommon varchar(1) COLLATE utf8_bin DEFAULT NULL,
recommender varchar(20) COLLATE utf8_bin DEFAULT NULL,
register_no varchar(20) COLLATE utf8_bin NOT NULL,
mobile_subscribe varchar(30) COLLATE utf8_bin DEFAULT NULL,
email_subscribe varchar(30) COLLATE utf8_bin DEFAULT NULL,
wechat_subscribe varchar(30) COLLATE utf8_bin DEFAULT NULL,
other_subscribe varchar(30) COLLATE utf8_bin DEFAULT NULL,
batch_id varchar(20) COLLATE utf8_bin DEFAULT NULL,
resby varchar(10) COLLATE utf8_bin NOT NULL,
reserved datetime NOT NULL,
ciby varchar(10) COLLATE utf8_bin DEFAULT NULL,
citime datetime DEFAULT NULL,
lostby varchar(10) COLLATE utf8_bin DEFAULT NULL,
losttime datetime DEFAULT NULL,
renewby varchar(10) COLLATE utf8_bin DEFAULT NULL,
renewtime datetime DEFAULT NULL,
applyby varchar(10) COLLATE utf8_bin DEFAULT NULL,
applytime datetime DEFAULT NULL,
haltby varchar(10) COLLATE utf8_bin DEFAULT NULL,
halttime datetime DEFAULT NULL,
cby varchar(10) COLLATE utf8_bin NOT NULL,
changed datetime NOT NULL,
tby varchar(10) COLLATE utf8_bin DEFAULT NULL,
ttime datetime DEFAULT NULL,
join_prom_code varchar(24) COLLATE utf8_bin DEFAULT NULL,
fv_date date DEFAULT NULL,
fv_hotel varchar(7) COLLATE utf8_bin DEFAULT NULL,
lv_date date DEFAULT NULL,
lv_hotel varchar(7) COLLATE utf8_bin DEFAULT NULL,
ref varchar(500) COLLATE utf8_bin DEFAULT NULL,
exp_s1 varchar(20) COLLATE utf8_bin DEFAULT NULL,
exp_s2 varchar(20) COLLATE utf8_bin DEFAULT NULL,
exp_s3 varchar(20) COLLATE utf8_bin DEFAULT NULL,
exp_s4 varchar(20) COLLATE utf8_bin DEFAULT NULL,
exp_s5 varchar(20) COLLATE utf8_bin DEFAULT NULL,
exp_s6 varchar(64) COLLATE utf8_bin DEFAULT NULL,
exp_s7 varchar(64) COLLATE utf8_bin DEFAULT NULL,
exp_s8 varchar(64) COLLATE utf8_bin DEFAULT NULL,
exp_s9 varchar(64) COLLATE utf8_bin DEFAULT NULL,
exp_s0 varchar(200) COLLATE utf8_bin DEFAULT NULL,
exp_m1 decimal(19,4) DEFAULT NULL,
exp_m2 decimal(19,4) DEFAULT NULL,
exp_m3 decimal(19,4) DEFAULT NULL,
exp_dt1 datetime DEFAULT NULL,
exp_dt2 datetime DEFAULT NULL,
exp_dt3 datetime DEFAULT NULL,
boss varchar(10) COLLATE utf8_bin DEFAULT NULL,
realname varchar(2) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (hotelid,id),
KEY index_applytime (applytime,applyby) USING BTREE,
KEY index_araccnt (araccnt1) USING BTREE,
KEY index_card_hotel (card_hotelid) USING BTREE,
KEY index_changed (changed) USING BTREE,
KEY index_cls (card_class) USING BTREE,
KEY index_cno (cno) USING BTREE,
KEY index_email_subscribe (email_subscribe) USING BTREE,
KEY index_flag (flag) USING BTREE,
KEY index_hno (hno) USING BTREE,
KEY index_hotelid (hotelid) USING BTREE,
KEY index_issue (issue_source) USING BTREE,
KEY index_mid (mid) USING BTREE,
KEY index_mobile_subscribe (mobile_subscribe) USING BTREE,
KEY index_no (no) USING BTREE,
KEY index_other_subscribe (other_subscribe) USING BTREE,
KEY index_pointaccnt (pointaccnt) USING BTREE,
KEY index_restime (reserved) USING BTREE,
KEY index_sno (sno) USING BTREE,
KEY index_sta (sta) USING BTREE,
KEY index_ticketaccnt (ticketaccnt) USING BTREE,
KEY index_type (type) USING BTREE,
KEY index_wechat_subscribe (wechat_subscribe) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

用代码块功能插入代码,请勿粘贴截图
运行结果及报错内容

explain
select c.no,c.name,(d.credit-d.charge) as bal
from vipcard c left join vipcard_ar_master d on c.araccnt1=d.accnt;
结果如下,没有用到索引
1 SIMPLE c null ALL null null null null 48685 100.00 null
1 SIMPLE d null ALL null null null null 36640 100.00 Using where; Using join buffer (Block Nested Loop)
mysql 版本5.7.37-log
select 中 (d.credit-d.charge) as bal去了,能用到索引了。

我想要达到的结果

请教高手。那里问题。

1、一个SQL是否利用索引会有很多很复杂的原因,光从SQL上看只能找到部分原因,需要看具体执行计划甚至数据结构
2、从SQL上看,你对左连接主表 vipcard 是全表数据提取,这个在所有数据库中都是全表扫描,想要利用索引,你得添加WHERE过滤条件,并且还得满足利用索引的各种复杂条件
3、而 vipcard_ar_master 表,虽然为左连接的从表且是主键关联,但在主表为全表扫描的前提下,这个表肯定只有全表扫描来对应了,走索引反而多些一举,更为低效
4、至于为啥 “ (d.credit-d.charge) as bal去了,能用到索引了 ”,这个是因为你的关联条件、提取结果集中涉及的所有列都有索引,只需要从各个索引中提取数据就能满足SQL的过滤和输出要求,不需要到表的数据区去提取数据,而且索引中的数据还是排好序的,比较起来更为快捷,这时系统判定走索引的远效率高于全表扫描的效率,自然只索引扫描了