mysql的索引使用的案例

  1. 单表索引优化案例
    1)表结构
          
    DROP TABLE IF EXISTS `article`;
    CREATE TABLE IF NOT EXISTS `article`(
    `id` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    `author_id` INT (10) UNSIGNED NOT NULL COMMENT '作者ID',
    `category_id` INT(10) UNSIGNED NOT NULL COMMENT '分类ID',
    `views` INT(10) UNSIGNED NOT NULL COMMENT '被查看次数',
    `comments` INT(10) UNSIGNED NOT NULL COMMENT '回帖的备注',
    `title` VARBINARY(255) NOT NULL COMMENT '文章主题',
    `content` TEXT NOT NULL COMMENT '文章内容'
    );
    INSERT INTO `article`(`author_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');
     
    SELECT * FROM article;

    2)需求
           查询category_id为1且comments大于1的情况下,views最多的article_d
    3)开始使用的sql
           SELECT id, author_id FROM article WHERE category_id = 1 and comments > 1 ORDER BY views DESC LIMIT 1;
            
    4)使用explain查看sql的执行计划
          
    可以发现type为ALL这个是全表扫描,而且在Extra中存在Using filesort这个也是最坏的情况,现在数据量小,后面一旦数据量上来,就会出现问题了,所以优化是必须的。
    5)开始创建索引进行sql优化
          a:根据where后面的条件创建组合索引
          
    CREATE INDEX idx_article_ccv on article(category_id,comments,views);
         b:查看索引
        
    6)再次执行sql计划看一下效果
        
    通过执行计划我们发现key中使用到了我们刚刚建立的索引了,并且type也变成了range,解决了全表扫描的问题,但是Extra
    中还是存在Using filesort问题,这个是为什么呢?
    7)问题分析
          因为上面我们建立的索引是三个字段category_id,comments,views。而条件1是category_id等于一个常量,那么我们使用
         上了索引,而我们的第二个字段comments却是一个范围的条件,范围的条件会导致索引的失效,从而导致mysql内部产生一个
        内部排序,最后导致后面的索引失效
    8)解决办法
        a:删除之前的索引
             
       b:上面的问题是因为comments的条件是一个范围,从而导致后面的索引都失效了,那么我们现在可以将comments这个字段
             的索引去掉,只留category_id和views两个字段的索引即可
            
       c:最后看一下效果
            
           可以发现不仅解决了Using filesort的问题,type也变成了ref级别,变得更快了。
  2. 双表索引优化案例
     1)表结构
           
    CREATE TABLE IF NOT EXISTS `class`(
    `id` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
    `card` INT (10) UNSIGNED NOT NULL COMMENT '分类card'
    );
    CREATE TABLE IF NOT EXISTS `book`(
    `bookid` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
    `card` INT (10) UNSIGNED NOT NULL COMMENT '分类card'
    );
    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 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)));
    

     2)需求
           使用class表左连接book表关联查询
    3)sql语句
          SELECT * FROM class c left join book b on c.card = b.card
    4)执行计划效果
         
         我们发现出现了全表扫描的问题。
    5)尝试先为book表的card字段添加索引试试
         
         在看执行效果:
         
        我们发现book表以及使用了索引,但是class表还是全表扫描。但是比上面的两个表都是全表扫描要好很多了。
    6)我们再尝试将book的索引去掉,在class的card字段上加上索引试试。
         
         查看执行结果:
          
          可以发现type由ref变为了index,说明效果不如将索引加在book表的card字段上好,而且这个效果的rows两张表
          都是20,效果比上面加在book表时的一个20,一个1的效果也要差。
         这是为什么呢?
    7)分析,为什么左连接时,索引加在右边的表比加在左边的表效果好呢?
           这个是由左连接的特性决定的,left join 条件用于确定如何从右表搜索行,而左边一定都有。所以右边是我们的关键点,
           右表一定要建立索引。所以我们还是要将当前的class表索引删掉,将book表的索引加上
           
    8)所以目前我们将索引建立在book这个右表上的效果是
         
    9)结论:
          左连接时,索引建立在右表,右连接时索引建立在左表。
          注意:上面的例子为什么不两张表都加上索引呢?因为这个是左连接,左表的表时查询所有数据,加不加没有意义。
  3. 三表索引优化案例
     1)表结构是在上面两张表的基础上加上一张phone表
          
    CREATE TABLE IF NOT EXISTS `phone`(
    `phoneid` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    `card` INT (10) UNSIGNED NOT NULL
    )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)));
    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)));
    

    2) 需求sql
         SELECT * FROM class c left join book b on c.card = b.card left join phone p on b.card = p.card;
    3)建立索引,在后面book表以及phone表的关联字段上建立索引
          
    4)执行sql计划,查看效果
           
           可以发现后两行的type都是ref,且rows都优化的很好。
    5)总结
          

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值