小言_互联网的博客

【MYSQL高级】索引优化

406人阅读  评论(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;

从图中可以看出: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.索引在两表中优化

  • 建表


  
  1. create table if not exists class(
  2. id int( 10) unsigned not null AUTO_INCREMENT,
  3. card int( 10) unsigned not null,
  4. primary key ( id)
  5. );
  6. create table if not exists book(
  7. bookid int( 10) unsigned not null AUTO_INCREMENT,
  8. card int( 10) unsigned not null,
  9. primary key(bookid)
  10. );
  11. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  12. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  13. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  14. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  15. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  16. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  17. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  18. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  19. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  20. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  21. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  22. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  23. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  24. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  25. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  26. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  27. insert into class (card) values( FLOOR( 1+( RAND()* 20)));
  28. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  29. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  30. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  31. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  32. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  33. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  34. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  35. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  36. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  37. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  38. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  39. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  40. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  41. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  42. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  43. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  44. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  45. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  46. insert into book (card) values( FLOOR( 1+( RAND()* 20)));
  47. 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.三表联查优化

  • 进行建表

  
  1. create table if not exists phone(
  2. phoneid int( 10) unsigned not null AUTO_INCREMENT,
  3. card int( 10) unsigned not null,
  4. primary key(phoneid)
  5. ) engine = innodb;
  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. insert into phone (card) values( FLOOR( 1+( RAND()* 20)));
  19. 沿用上面的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的设置。 

 

 

 

 

 


转载:https://blog.csdn.net/weixin_43271086/article/details/105396715
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场