mysql之索引优化案例一

  1. 创建表结构以及相关索引
    CREATE TABLE staffs(
    id INT PRIMARY KEY AUTO_INCREMENT,
    `name` VARCHAR(24)NOT NULL DEFAULT'' COMMENT'姓名',
    `age` INT NOT NULL DEFAULT 0 COMMENT'年龄',
    `pos` VARCHAR(20) NOT NULL DEFAULT'' COMMENT'职位',
    `add_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT'入职时间'
    )CHARSET utf8 COMMENT'员工记录表';
    INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('z3',22,'manager',NOW());
    INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('July',23,'dev',NOW());
    INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('2000',23,'dev',NOW());
    
    ALTER TABLE staffs ADD INDEX index_staffs_nameAgePos(`name`,`age`,`pos`);
    
    CREATE TABLE `tbl_user`(
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(20) DEFAULT NULL,
    `age`INT(11) DEFAULT NULL,
    `email` VARCHAR(20) DEFAULT NULL,
    PRIMARY KEY(`id`)
    )ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    INSERT INTO tbl_user(`name`,`age`,`email`)VALUES('1aa1',21,'a@163.com');
    INSERT INTO tbl_user(`name`,`age`,`email`)VALUES('2bb2',23,'b@163.com');
    INSERT INTO tbl_user(`name`,`age`,`email`)VALUES('3cc3',24,'c@163.com');
    INSERT INTO tbl_user(`name`,`age`,`email`)VALUES('4dd4',26,'d@163.com');
    
    
  2. 对应最佳左前缀法则
    1)需求描述:
          查询年龄为23,职位是dev的员工
     2)sql语句
           SELECT * from staffs where age = '23' and pos = 'dev'
     3)查看执行计划
            
            可以发现出现了全表扫描。索引竟然没有用到
     4) 我们在使用下面的sql试一下
            
            
               
            
     5)通过上面发现
            我们创建的索引是index_staffs_nameAgePos,那么sql语句中条件必须存在name,如果单独存在age或者pos,
            以及同时存在age和pos但是不存在name,那么索引都不会生效。这个是因为它违背了最佳左前缀法则。
            
          
     6)总结
           按照我们上面建立索引的方式,我们在查询条件的时候必须按照顺序去作为条件查询,否则会导致索引失效,
           注意:这里的顺序不是查询条件的顺序,而是索引的顺序,就是说,我们创建索引的顺序是name,age,pos,
           name在条件里面必须存在name,否则索引失效,如果存在name了,想要pos字段索引也生效,name必须存在
          age,否则pos不会生效。
  3. 不在索引列上做任何操作(计算,函数,(自动or手动)类型转换)会导致索引失效而转向全表扫描
    1)我们使用left函数查询
         
    2)使用执行计划看看
           
  4. 存储引擎不能使用索引中范围条件右边的列
     
  5. 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
     
  6. mysql在使用不等于(!=或者<>)的时候无法使用索引,会导致全表扫描
  7. is null,is not null也会导致全表扫描
  8. like以通配符开头('%abc...')也会导致全表扫描

    可以发现在右边写百分号,还是可以走索引的。
    那么如何解决这个like的问题呢?
    1) 首先我们为tb1_user表创建索引
          
    2)使用覆盖索引解决全表扫描的问题
          我们只查建立了索引的字段name和age(只查name或者age也可以)
           
    3)只查询主键也可以走索引(没啥意义,业务中几乎不可能只查主键)
          
    4)但是加上其它的字段就会导致索引失效
          
          
  9. 字符串不加单引号索引失败
  10. 少用or,用它来连接时会导致索引失效
### MySQL 索引优化的实际案例 #### 创建和使用组合索引 在一个实际项目中,假设有一个 `users` 表用于存储用户信息。该表包含多个字段如 `id`, `name`, `age`, `gender`, 和 `city_id`。为了提高查询效率,在设计索引时选择了创建组合索引来满足常见的多条件联合查询需求。 对于经常使用的查询语句如下所示: ```sql SELECT id, name FROM users WHERE city_id = ? AND gender = ? ``` 针对上述SQL语句的特点,可以为 `(city_id, gender)` 列创建一个复合索引,这样当执行这类带有两个条件的查询时就能显著提升速度[^1]。 #### 使用 EXPLAIN 查看并分析查询计划 在实施任何索引调整之前,应该总是先运行 `EXPLAIN` 来观察当前查询是如何被执行的。这有助于理解现有索引的工作方式以及是否存在潜在改进空间。 例如,可以通过下面命令来检查上面提到的那个查询是否有良好表现: ```sql EXPLAIN SELECT id, name FROM users WHERE city_id = 123 AND gender = 'male'; ``` 理想情况下,输出结果中的 `key` 字段应显示所定义的组合索引名称;而在 `rows` 列则显示出预计扫描到的数据行数越少越好,表明更高效地利用到了索引结构。 #### 避免不等于操作影响索引效能 需要注意的是某些特定类型的比较运算符索引造成负面影响。特别是像 `!=` 或者 `NOT IN` 这样的否定表达式往往使MySQL放弃使用已存在的索引路径,转而采取全表扫描的方式完成检索工作。因此应当尽量避免编写含有此类逻辑的操作[^2]。 #### 应用覆盖索引减少I/O开销 考虑到读取整条记录可能导致不必要的磁盘访问增加延迟时间,所以建议尽可能构建能够完全服务于目标查询请求所需的最小化索引集——也就是所谓的“覆盖索引”。这意味着只要通过一次索引树遍历即可获取全部所需数据项,无需再回到原始表去加载额外的信息片段[^3]。 例如,如果我们只需要返回用户的ID和名字,并且这两个属性已经被加入到了前面所说的组合索引里,则此时就可以享受到这种技术带来的好处了。 ```sql CREATE INDEX idx_city_gender ON users(city_id, gender); ALTER TABLE users ADD COLUMN nickname VARCHAR(50); -- 原始查询可能触发回表动作 SELECT id, name FROM users WHERE city_id = 123 AND gender = 'female'; -- 修改后的版本尝试利用覆盖索引特性 SELECT id, name FROM users USE INDEX (idx_city_gender) WHERE city_id = 123 AND gender = 'female'; ``` 以上便是几个有关于MySQL索引优化的具体实践例子,它们展示了如何基于业务特点合理规划索引策略从而达到更好的性能指标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值