mysql join查询时,参与join的字段字符集编码不同,对性能影响是巨大的

本文一直以来都只是个标题,在三个月后的今天,熬夜补上内容。

直接上代码:

建utf-8编码的表 t1:

CREATE TABLE IF NOT EXISTS `t1` (
  `name` varchar(50) NOT NULL DEFAULT '',
  KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

随便插入些数据,数量大一点,后面实验结果更清晰,偷个懒,构造随机字符串插入语句

insert into t1(name) 
select concat(
char(round((rand())*25)+97),
char(round((rand())*25)+65),
char(round((rand())*25)+65),
char(round((rand())*25)+97),
char(round((rand())*25)+65),
char(round((rand())*25)+65),
char(round((rand())*25)+97),
char(round((rand())*25)+65)
)

每次执行插入一条记录,用你熟悉的脚本(python,php,shell等都行)写个循环,执行一万次以上。

将该表复制成一个新表t2,删除一部分数据,1000条左右即可。(推荐使用phpMyAdmin)

再将t2复制为t3,并将字段改为gb2312编码。

使用一个left join语句,写一个语句,查出t2/t3比t1少了哪些记录。

语句很简单,如下:

SELECT SQL_NO_CACHE t1.name, t2.name
FROM t1
LEFT JOIN t2 ON t1.name = t2.name
WHERE t2.name IS NULL 
LIMIT 0 , 30

注意加入 SQL_NO_CACHE ,禁用mysql缓存。

先看编码一致的t2表,phpMyAdmin里执行结果:

显示行 0 - 29 ( 1,129 总计, 查询花费 0.0010 秒)

平均耗时大概为0.0010秒

SELECT SQL_NO_CACHE t1.name, t3.name
FROM t1
LEFT JOIN t3 ON t1.name = t3.name
WHERE t2.name IS NULL 
LIMIT 0 , 30

phpMyAdmin执行结果:

显示行 0 - 29 ( 30 总计, 查询花费 0.1871 秒)

差两个数量级!

查询语句解释:

t2

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL name 152 NULL 11129 Using index
1 SIMPLE t2 ref name name 152 test.t1.name 1 Using where; Using index; Not exists

t3

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL name 152 NULL 11129 Using index
1 SIMPLE t3 index NULL name 102 NULL 10000 Using where; Using index; Not exists

附带上本次实验的三个表及数据
实验用表导出备份test.sql

 

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据