数据表 rm_ic.audit_summary_2024_05_20 该表大概有1200w数据,有个字段为ids 不是唯一的,已建索引 audit_ids_idx
create table rm_ic.test1
(
id varchar(19) primary key not null comment 'id',
create_time datetime default CURRENT_TIMESTAMP
);
create table rm_ic.test2
(
id varchar(19) charset utf8 primary key not null comment 'id',
create_time datetime default CURRENT_TIMESTAMP
);
-- 插入十万条 ids数据
insert into rm_ic.test1 select ids,sysdate() from (select distinct ids from rm_ic.audit_summary_2024_05_20 limit 100000)t ;
insert into rm_ic.test2 select ids,sysdate() from (select distinct ids from rm_ic.audit_summary_2024_05_20 limit 100000)t ;
关键来了,因为ids可能重复,我们test表id不重复,简单的count()下
select count(1) from rm_ic.audit_summary_2024_05_20 inner join rm_ic.test1 w on ids=w.id where 1=1;
select count(1) from rm_ic.audit_summary_2024_05_20 inner join rm_ic.test2 w on ids=w.id where 1=1;
看到真相的我眼泪都要掉下来,怎么一个test2=0.5s,test1=13s呢?结果数据count都是一样的呀,
test1和test2的id字段都是主键啊?难道没走索引,难道有其他问题?explain来解释下把
可以看到test1的innerjoin
test1表是eq_ref,summary=index
test2表是index,summary=ref
众所周知eq_ref>ref>index
上面说了sumamry表数据为1200w,test表都只有10w 那么肯定是summary表查询走ref>index的查询速度的。
那么为什么造成这样的区别呢?test1和test2表有什么区别呢?建表的时候id指定了字符集?
MySQL查看和修改数据库字符集的方法_修改数据库字符集sql-CSDN博客
方法一:show variables like '%character%';
方法二:show variables like 'collation%';
2.查看库的字符集
show create database rm_ic;
查看表的字符集
show table status from 库名 like 表名;
查看表中所有列的字符集
show full columns from 表名;
可以看到数据库默认的编码 utf8mb4_bin
audit_summary表的ids字段 utf8_general_ci
test1的id字段是 utf8mb4_bin
test2的id字段是 utf8_general_ci
因为test1的id字段是和summary字段的ids字段编码集不一样,所以导致索引失效,懒得研究了直接百度 mysql编码集不一样导致索引失效
MySQL表字段字符集不同导致的索引失效问题_表字符集不一致导致索引失效-CSDN博客
test2为什么查询比较快?因为test2数据量为10w小表,默认是驱动表,也就是先通过index查test2,然后驱动大表test1为什么查询比较慢呢?因为先全表扫描1000w的大表audit_summary,然后再根据关联条件查询test1.
字符集转换遵循由小到大的原则,因为utf8mb4是utf8的超集,所以这里把utf8转换成utf8mb4,也就是先查询utf8的summary表然后将其转化。
-------最后说下------
为什么会造成这个原因呢?一般来说我们都是默认字符集的,那么所有的字符集应该一样啊。
原因是我们之前的版本字符集是utf8,后来发现不能存emoj 😀 就是这种字符,后面就把数据的字符集改了改为 utf8mb4,然后新表和旧表的字符集就对不上了。。