单表
1.创建表
1
2
3
4
5
6
7
8
9create tables if not exists article(
id int unsigned primary key not null auto_increment,
author_id int unsigned not null,
category_id int unsigned not null,
comments int unsigned not null,
views int unsigned not null,
tiltle varbinary(255) not null,
content TEXT(255) not null
);2.插入数据
1
insert into article(author_id, category_id, comments, views, title, content) vlaues (1,1,1,1,’1’,’1’), (2,2,2,2,’2’,’2’),(1,1,3,3,’3’,’3’);
3.explain
1
explain select author_id, id from article where category_id=1 and comments>1 oder by views limit 1;
这个时候是全表扫描,type为all效率极低。
4.建立联合索引
我们按where筛选顺序建立联合索引1
create index idx_article_ccv on article(category_id, comments, views);
5.再次explain
1
explain select author_id, id from article where category_id=1 and comments>1 oder by views limit 1;
发现type为range extras有file_sort
分析:由于comments是大于1的一个范围值,不具备索引查找条件,
所以联合索引到comments就失效了,所以我们需要重新建立不包含comments的联合索引6.重新建立联合索引
create index idx_article_cv on article(category_id, views);
再次explain select author_id, id from article where category_id=1 and comments>1 oder by views limit 1;
发现type变为ref,file_sort消失。
优化结束。
两表
当通过连接进行的sql会如何进行优化sql?
1.创建表
1
2
3
4
5
6
7
8create table if not exists class(
id int unsigned not null primary key auto_increment,
card int unsigned not null
);
create table if not exists book(
bookid int unsigned not null primary key auto_increment,
card int unsigned not null
);2.插入数据
随便给两张表插入点数据1
insert into class(card) values(floor(1+rand(20)));
3.explain
1
explain select * from class left join book on class.card=book.card
这个时候没有建立索引我们发现type都为all
那我们到底是给left join的左表建立索引还是右表?
分析:左边建立索引就是full index scan,type为index,而右边建立索引就是非唯一索引扫描,通
过左边筛选出的card去找寻对应的card,所以右边type为ref,果断选择建立右表索引。
1 | alter table book add index idx_book_card (card); |
- 4.再次explain,发现分析正确。建索引应该建立在从表上。
(如果两表都建索引呢)??????
三表
- 1.建表
再新建一个表phone分析:其实思路和双表一样,两个外表都建立索引1
2
3
4create table if not exists phone(
phoneid int unsigned not null primary key auto_increment,
card int unsigned not null
);
join语句优化总结:
1.尽可能减少join语句中的nestedLoop的循环总次数:永远用小的结果集驱动大的结果集,小表驱动大表。
2.保证join语句被驱动表上join条件字段已经被索引:
当无法保证被驱动表的join字段被索引且内存资源充足的前提下,不要太吝惜joinbuffer的设置
3.以上都是mysql5.7的检测结果,msyql8后连表查询有所改变