mysql explain type的区别和性能优化

mysql查看性能工具explain中type有很多种,主要的有:

链接类型说明
system表只有一行MyISAM引擎。
const常量连接,表最多只有一行匹配,通用用于主键或者唯一索引比较时
eq_ref每次与之前的表合并行都只在该表读取一行,这是除了system,const之外最好的一种,特点是使用=,而且索引的所有部分都参与join且索引是主键非空唯一键的索引
ref如果每次只匹配少数行,那就是比较好的一种,使用=或<=>,可以是左覆盖索引或非主键非唯一
fulltext全文搜索
ref_or_nullref类似,但包括NULL
index_merge表示出现了索引合并优化(包括交集,并集以及交集之间的并集),但不包括跨表和全文索引。这个比较复杂,目前的理解是合并单表的范围索引扫描(如果成本估算比普通的range要更优的话)
unique_subquery在in子查询中,就是value in (select…)把形如select unique_key_column的子查询替换。PS:所以不一定in子句中使用子查询就是低效的!
index_subquery同上,但把形如”select non_unique_key_column“的子查询替换
range常数值的范围
index索引树扫描。a.当查询是索引覆盖的,即所有数据均可从索引树获取的时候(Extra中有Using Index);b.以索引顺序从索引中查找数据行的全表扫描(无 Using Index);c.如果Extra中Using Index与Using Where同时出现的话,则是利用索引查找键值的意思;d.如单独出现,则是用读索引来代替读行,但不用于查找
all全表扫描(full table scan)

现在把主要的实现一下,以下性能越来越慢。

system > const > eq_ref > ref > range > index > ALL

system

CREATE TABLE `news` (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `news` (`id`, `title`) VALUES
(1, 'test');
explain select * from news where id=1;

system
主键或唯一索引查找常量值,只有一条记录,并且是MyISAM引擎。

const

INSERT INTO `news` (`id`, `title`) VALUES (NULL, 'test1');
EXPLAIN select * from news where id=1;

const
const扫描的条件为:
(1)命中主键(primary key)或者唯一(unique)索引;
(2)被连接的部分是一个常量(const)值;

eq_ref

CREATE TABLE `content` (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `news_id` int(10) UNSIGNED NOT NULL,
  `content` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `content` (`id`, `news_id`, `content`) VALUES (NULL, '1', 'content');
INSERT INTO `content` (`id`, `news_id`, `content`) VALUES (NULL, '2', 'content2');
EXPLAIN SELECT * FROM `news` JOIN `content` ON news.id=content.news_id;

eq_ref
eq_ref扫描的条件为,对于前表的每一行(row),后表只有一行被扫描。
(1)join查询;
(2)命中 主键(primary key) 或者 非空唯一(unique not null) 索引;
(3)等值连接;

ref

ALTER TABLE `news` ADD INDEX(`title`);
explain SELECT * FROM news where title="test";

ref
当id改为普通非唯一索引后,常量的连接查询,也由const降级为了ref,因为也可能有多于一行的数据被扫描。
ref扫描,可能出现在join里,也可能出现在单表普通索引里,每一次匹配可能有多行数据返回,虽然它比eq_ref要慢,但它仍然是一个很快的join类型。

range

explain SELECT * FROM news where id>1;


betweenin>都是典型的范围(range)查询。

index

如果是MyISAM引擎,type是NULL。
null

ALTER TABLE `news` ENGINE = InnoDB;
explain SELECT count(*) FROM news;

index
index类型,需要扫描索引上的全部数据

ALL

explain select * from content;

ALL
system最快:很少能出现。
const:PK或者unique上的等值查询
eq_ref:PK或者unique上的join查询,等值匹配,对于前表的每一行(row),后表只有一行命中
ref:非唯一索引,等值匹配,可能有多行命中
range:索引上的范围扫描,例如:between/in/>
index:索引上的全集扫描,例如:InnoDB的count
ALL最慢:全表扫描(full table scan)

  • 24
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小龙在山东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值