【MYSQL高级】索引优化

待我称王封你为后i 2021-10-03 02:04 642阅读 0赞

1.先来学习索引的一些语法:

  • 展示索引

    • show index from 表名;
  • 创建索引

    • create index 索引名 on 表名(字段1,字段2,…);
  • 删除索引

    • Drop index 索引名 on 表名;

2.索引在单表中的操作:

1.进行(单表)建表操作

  1. create table if not exists article(
  2. id int(10) unsigned not null primary key AUTO_INCREMENT,
  3. auther_id int(10) unsigned not null,
  4. category_id int(10) unsigned not null,
  5. views int(10) unsigned not null,
  6. comments int(10) unsigned not null,
  7. title varbinary(255) not null,
  8. content text not null
  9. );
  10. insert into article(auther_id,category_id,views,comments,title,content)values
  11. (1,1,1,1,'1','1'),
  12. (2,2,2,2,'2','2'),
  13. (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;

20200408205340821.png

从图中可以看出:type类型是ALL,并且出现了Using filesort(内排序的字段) 。ALL说明是全表扫描,这在一定程度上降低了速度,所以需要进行优化。

3.进行建立索引的操作

  • 建立索引的原则就是给where后面的字段都创建成索引。

create index idx_article_ccv on article(category_id,comments,views);

20200408205733423.png

可以看出:虽然由ALL变成了range,但是还是没有解决Using filesort(内排序)的问题,这是因为comments在进行查找的时候系统自己进行了排序,因为他不是常量导致了索引失效。

  • 进行再一次的优化

create index idx_article_cv on article(category_id,views);

20200408210042982.png

这次就解决了所有问题,而且达到了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;

20200408210311675.png

可以看到type类型还是ALL

  • 进行优化操作

alter table book ADD INDEX Y (card);

20200408210420336.png

book作为右表加上优化之后,达到了ref水准。

删除索引:
drop index Y on book;
alter table class ADD INDEX Y (card);

2020040821045394.png

结论:左连接加在右表,右连接相反。
这是由于左连接的特性决定的。LEFT JOIN 条件用于确定如何从右表搜索行,左边一定都有。

4.三表联查优化

  • 进行建表

    create table if not exists phone(

    1. phoneid int(10) unsigned not null AUTO_INCREMENT,
    2. card int(10) unsigned not null,
    3. primary key(phoneid)
    4. )engine = innodb;
    5. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    6. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    7. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    8. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    9. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    10. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    11. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    12. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    13. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    14. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    15. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    16. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    17. insert into phone (card) values(FLOOR(1+(RAND()*20)));
    18. 沿用上面的bookclass表进行操作
  • 进行三表查询操作

explain select * from class left join book on class.card = book.card left join phone on book.card = phone.card;

20200408210621156.png join buffer 表示使用了缓存

  • 进行优化操作

alter table phone ADD index z(card);
alter table book ADD index y(card);

20200408210728726.png

结论:尽可能减少join语句中的NestedLoop(嵌套循环)的循环总次数:‘永远用小的结果集驱动大的结果集’。
优先优化嵌套循环中的内层循环;
保证join语句中被驱动表上的join条件字段已经被索引。
当无法保证被驱动表的join条件字段被索引且内存充足的前提下,不要太吝啬JoinBuffer的设置。

发表评论

表情:
评论列表 (有 0 条评论,642人围观)

还没有评论,来说两句吧...

相关阅读

    相关 MySQL高级性能优化---索引

    1. 什么是索引 帮助Mysql高效获取数据的数据结构,索引就是一种数据结构,这种数据结构类似新华字典的索引目录, 可以通过索引目录快速查到你想要的字,排好序的快速查找数