首页 > 数据库 >mysql 深入学习三 索引优化一

mysql 深入学习三 索引优化一

时间:2023-08-26 17:34:59浏览次数:45  
标签:hire name age 索引 mysql position 优化

测试建表

CREATE TABLE `employees` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',
    `age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',
    `position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',
    `hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',
    PRIMARY KEY (`id`),
    KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='员工记录表';
 
INSERT INTO employees(name,age,position,hire_time) VALUES('LiLei',22,'manager',NOW());
INSERT INTO employees(name,age,position,hire_time) VALUES('HanMeimei', 23,'dev',NOW());
INSERT INTO employees(name,age,position,hire_time) VALUES('Lucy',23,'dev',NOW());

注意: 联合索引:KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE

全值匹配

  1.联合索引中只利用‘name’字段索引: key_len = ‘name’字段长度 ( 存汉字则长度是 3n + 2 字节)  3*24+2

  2.联合索引中利用 ‘name’ 和 ‘age’ 字段索引: key_len = ‘name’字段长度 + 'age'字段长度(int:4字节)

  3.联合索引中全部利用 ‘name’ 、‘age’和 ‘position’ 字段索引 : key_len = ‘name’字段长度 + 'age'字段长度+‘position’字段长度 (( 存汉字则长度是 3n + 2 字节)  3n+2)3*20+2

    注意:修改索引字段顺序,mysql会优化成定义的联合索引的顺序,尽管不影响使用,但还是建议使用定义的联合索引的顺序

最左前缀法则

  如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。   错误示例一:跳过了age索引,只有name索引生效,position索引不生效  

   错误示例二:未使用name索引,导致其他两个索引失效,整体未使用索引

   错误示例二:未使用 ‘name’  和 ‘age’ 索引,导致 'position' 索引 失效,整体未使用索引

不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

   1.此处在 ‘name’索引字段上使用了 left()函数操作,导致不走索引:因为left()函数运算后的值在索引树上不一定能找得到值

   2.测试前执行:ALTER TABLE `employees` ADD INDEX `idx_hire_time` (`hire_time`) USING BTREE ; #给hire_time增加一个普通索引:

    此处在 ‘hire_time’索引字段上使用了 date()函数操作,导致不走索引

  

    可以优化为日期范围查询,有可能会走索引:注意此处key列也有可能为Null,不走索引,这里mysql底层会根据评估值来进行选择是否走索引,这里《抛出问题一》

     测试后执行:ALTER TABLE `employees` DROP INDEX `idx_hire_time`; #删除hire_time的普通索引

存储引擎不能使用索引中范围条件右边的列 

  注意key_len 为78,说明只走了 'name' 和 ‘age’ 索引,是因为 ‘age’ 索引是范围索引,不能保证 ‘position’ 索引的无序性,所以 ‘position’ 索引未生效

尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),减少 select * 语句 。(覆盖索引不需要回表查询,只需要在索引表就完成查询了)

   使用覆盖索引

   未使用覆盖索引

mysql在使用不等于(!=或者<>),not in ,not exists 的时候无法使用索引会导致全表扫描

< 小于、 > 大于、 <=、>= 这些,mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引

is null,is not null 一般情况下也无法使用索引

like以通配符开头('%abc...')mysql索引失效会变成全表扫描操作 

  注意:‘%Lei’ 没走索引

   注意,‘Lei%’ 走了索引 。区别left(name, 3)的函数情况,因为explain没有对函数做底层优化!毕竟explain并不是真的执行sql语句,只是分析

   解决一:那么如何优化 ‘%Lei’ 这种情况呢? 使用覆盖索引

  解决二:如果不能使用覆盖索引则可能需要借助搜索引擎 

字符串不加单引号索引失效 

 

少用or或in,用它查询时,mysql不一定使用索引,mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引,详见范围查询优化

范围查询优化 

  测试前添加:ALTER TABLE `employees` ADD INDEX `idx_age` (`age`) USING BTREE ; #age字段添加索引

  没走索引原因:mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引。比如这个例子,可能是由于单次数据量查询过大导致优化器最终选择不走索引   优化方法:可以将大的范围拆分成多个小范围(注意:多大范围内使用索引是由mysql来评估的,是否跟表字段最大值有关?)

   测试后添加:ALTER TABLE `employees` DROP INDEX `idx_age`; #age字段删除索引

 

-- mysql5.7关闭ONLY_FULL_GROUP_BY报错 select version(), @@sql_mode;SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));   

 

标签:hire,name,age,索引,mysql,position,优化
From: https://www.cnblogs.com/ruber/p/17658924.html

相关文章

  • 【MySQL 8.0】新特性:支持CHECK约束
    (root@node01)>createtablestudent(idintprimarykey,namevarchar(255),ageint,genderchar(1),scorefloat,constraintchk_agecheck(age>=18),constraintchk_scorecheck(score>=0andscore<=100));QueryOK,0rowsaffected(0.20......
  • MySQL 一行记录是怎么存储的?
    一、数据存在哪个文件可以看到,共有三个文件,这三个文件分别代表着:db.opt,用来存储当前数据库的默认字符集和字符校验规则。t_order.frm,t_order的表结构会保存在这个文件。在MySQL中建立一张表都会生成一个.frm文件,该文件是用来保存每个表的元数据信息的,主要包含表结构定义......
  • bitset优化01可行背包
    例题传送门:『STA-R3』Aulvwc先讲bitset用法:1,基础下标:\(5~4~3~2~1~0\)数字:\(0~0~0~0~1~0\)\(bitset\)<\(n\)>\(s\)表示一个\(n\)位的二进制数,空间复杂度:\(O(\frac{n}{32})\),可见其非常优秀因为其跟二进制有关,所以可以使用\(\&,|,\land\)对两个位数相同的\(bitset\)执行按......
  • 【MySQL 8.0】通过pt-archiver实现表的历史数据归档
    (root@node02)>setgloballocal_infile=on;QueryOK,0rowsaffected(0.00sec)(root@node02)>createtablecustomer_jplikecustomer;QueryOK,0rowsaffected(0.20sec)(root@node01)>setgloballocal_infile=on;QueryOK,0rowsaffected......
  • 启动mysql数据库时报错unknown variable 'rpl_semi_sync_slave_enabled=1'
    问题描述:启动mysql数据库时报错unknownvariable'rpl_semi_sync_slave_enabled=1'.数据库:mysql5.7.21系统:rhel7.31、异常重现--启动数据库[mysql@mysql-leo-slavedata]$/usr/local/mysql/bin/mysqld_safe--defaults-file=/home/mysql/etc/my.cnf&--告警信息2023-08-......
  • mongo判断某些字段上有没有索引,进行动态创建
    IndexOptions:privatebooleanbackground;privatebooleanunique;privateStringname;privatebooleansparse;privateLongexpireAfterSeconds;privateIntegerversion;privateBsonweights;privateStringdefaultLanguage;......
  • 多元回归预测 | Matlab 粒子群算法优化随机森林(PSO-RF)回归预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 多元回归预测 | Matlab 鲸鱼算法优化随机森林(WOA-RF)回归预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 【MySQL 8.0】通过pt-heartbeat监控从库与主库的复制延迟
    [root@node01~]#wgethttps://repo.percona.com/yum/percona-release-latest.noarch.rpm[root@node01~]#rpm-ivhpercona-release-latest.noarch.rpm[root@node01~]#yuminstall-ypercona-toolkit[root@node01~]#pt-heartbeat--versionpt-heartbeat3.5.2[......
  • SQL Server 相比 MySQL 有何优势?
    两种产品并不是一样的类型,mysql是单纯的数据库存储,mssql是一整套数据解决方案。如果有兴趣可以去了解一下microsoftsqlserverbusinessintelligence和datamining相关的产品,以及datacube,高斯分布计算等各种features,你就会改变观念了。mysql是互联网公司广泛使用的,免费的(最重......