【MYSQL高级】索引优化
1.先来学习索引的一些语法:
展示索引
- show index from 表名;
创建索引
- create index 索引名 on 表名(字段1,字段2,…);
删除索引
- Drop index 索引名 on 表名;
2.索引在单表中的操作:
1.进行(单表)建表操作
create table if not exists article(
id int(10) unsigned not null primary key AUTO_INCREMENT,
auther_id int(10) unsigned not null,
category_id int(10) unsigned not null,
views int(10) unsigned not null,
comments int(10) unsigned not null,
title varbinary(255) not null,
content text not null
);
insert into article(auther_id,category_id,views,comments,title,content)values
(1,1,1,1,'1','1'),
(2,2,2,2,'2','2'),
(1,1,3,3,'3','3');
2.进行查询操作
查询 category_id 为 1 且 comments大于1的情况下,views最多的 auther_id。
explain select id,auther_id from article where category_id = 1 AND comments>1 order by views DESC LIMIT 1;
从图中可以看出:type类型是ALL,并且出现了Using filesort(内排序的字段) 。ALL说明是全表扫描,这在一定程度上降低了速度,所以需要进行优化。
3.进行建立索引的操作
- 建立索引的原则就是给where后面的字段都创建成索引。
create index idx_article_ccv on article(category_id,comments,views);
可以看出:虽然由ALL变成了range,但是还是没有解决Using filesort(内排序)的问题,这是因为comments在进行查找的时候系统自己进行了排序,因为他不是常量导致了索引失效。
- 进行再一次的优化
create index idx_article_cv on article(category_id,views);
这次就解决了所有问题,而且达到了ref的状态。
3.索引在两表中优化
建表
create table if not exists class(
id int(10) unsigned not null AUTO_INCREMENT,
card int(10) unsigned not null,
primary key (id)
);
create table if not exists book(
bookid int(10) unsigned not null AUTO_INCREMENT,
card int(10) unsigned not null,
primary key(bookid)
);insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()20)));
insert into class (card) values(FLOOR(1+(RAND()*20)));insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));
insert into book (card) values(FLOOR(1+(RAND()20)));查询book的card和class的card相等。(左连接)
explain select * from book left join class on book.card = class.card;
可以看到type类型还是ALL
- 进行优化操作
alter table book ADD INDEX Y (card);
book作为右表加上优化之后,达到了ref水准。
删除索引:
drop index Y on book;
alter table class ADD INDEX Y (card);
结论:左连接加在右表,右连接相反。
这是由于左连接的特性决定的。LEFT JOIN 条件用于确定如何从右表搜索行,左边一定都有。
4.三表联查优化
进行建表
create table if not exists phone(
phoneid int(10) unsigned not null AUTO_INCREMENT,
card int(10) unsigned not null,
primary key(phoneid)
)engine = innodb;
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
insert into phone (card) values(FLOOR(1+(RAND()*20)));
沿用上面的book和class表进行操作
进行三表查询操作
explain select * from class left join book on class.card = book.card left join phone on book.card = phone.card;
join buffer 表示使用了缓存
- 进行优化操作
alter table phone ADD index z(card);
alter table book ADD index y(card);
结论:尽可能减少join语句中的NestedLoop(嵌套循环)的循环总次数:‘永远用小的结果集驱动大的结果集’。
优先优化嵌套循环中的内层循环;
保证join语句中被驱动表上的join条件字段已经被索引。
当无法保证被驱动表的join条件字段被索引且内存充足的前提下,不要太吝啬JoinBuffer的设置。
还没有评论,来说两句吧...