Mysql优化

MySQL优化

索引能大大的提高查询速度, 但同时会降低更新表的速度,因对表进行 INSERTUPDATEDELETE操作时,MySQL 不仅要保存数据,还要维护一下索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究如何 建立最优秀的索引优化查询语句。 那么如何优化索引呢,以下是一些总结的MySQL 索引注意事项和SQL优化方法:

1. 何时使用聚集索引或非聚集索引?

动作描述使用聚集索引使用非聚集索引
列经常被分组排序使用使用
返回某范围内的数据使用不使用
一个或极少不同值不使用不使用
小数目的不同值使用不使用
大数目的不同值不使用使用
频繁更新的列不使用使用
外键列使用使用
主键列使用使用
频繁修改索引列不使用使用

2. 索引不会包含有NULL值的数据

单列索引不存NULL值,复合索引不存全为NULL的值,如果列允许为NULL,可能会得到不符合预期的结果集(NULL的列如果是索引,则为NULL的列不进入索引里)。例如:如果 name允许为NULL,索引不存储NULL值,结果集中不会包含这些记录。所以,请使用 NOT NULL约束及默认值

所以说索引字段最好不要为NULL,因为NULL会使索引、索引统计和值更加复杂,并且需要额外一个字节的存储空间。

3.使用短索引(前缀索引)

有时需要索引很长的字符列, 它会使索引变大并且变慢。 例如:有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引,而应该创建短索引(前缀索引)。 短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

4. 索引列排序

大多数情况下MySQL一个查询语句一张表只会使用一个索引,因此如果 WHERE子句中已经使用了索引的话,那么ORDER BY中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作; 尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

5.尽量全值匹配

使用复合索引时,尽量包含索引的所以列

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` bigint NOT NULL AUTO_INCREMENT ,
  `username` varchar(10) NOT NULL ,
  `password` varchar(20) NOT NULL ,
  `name` varchar(10) NOT NULL ,
  `idCard` char(10) DEFAULT NULL ,
  `age` int NOT NULL ,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_user` (`name`,`idCard`,`age`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

EXPLAIN SELECT * FROM users WHERE name='admin';
EXPLAIN SELECT * FROM users WHERE name='admin' AND idcard='1234';
EXPLAIN SELECT * FROM users WHERE name='admin' AND idcard='1234' AND age = 20;

查看以上SQL语句执行计划
在这里插入图片描述
使用同一个索引的情况下,key_len值越大表示更充分的使用了索引。

6.最佳左前缀法则

如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且 不跳过索引中的列

EXPLAIN SELECT * FROM users WHERE age=20;
EXPLAIN SELECT * FROM users WHERE idcard='1234' AND age = 20;
EXPLAIN SELECT * FROM users WHERE name='admin';

在这里插入图片描述

7.不在索引列上做任何操作

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

EXPLAIN SELECT * FROM users WHERE LOWER(name)='admin';

在这里插入图片描述

8.范围条件放最后

ALTER TABLE users DROP INDEX idx_user;
ALTER TABLE users ADD KEY idx_user (name,age,idcard);

EXPLAIN SELECT * FROM users WHERE name='admin' AND idcard='1234' AND age > 20;
EXPLAIN SELECT * FROM users WHERE name='admin' AND age > 20 AND idcard='1234';
EXPLAIN SELECT * FROM users WHERE name='admin' AND age > 20;

在这里插入图片描述
发现并没有充分用到索引,优化重建索引

ALTER TABLE users DROP INDEX idx_user;
ALTER TABLE users ADD KEY idx_user (name,idcard,age);
EXPLAIN SELECT * FROM users WHERE name='admin' AND idcard='1234' AND age > 20;

在这里插入图片描述

9.尽量使用覆盖索引

​ 只访问索引的查询(索引列和查询列一致),减少select *

在这里插入图片描述

10.不等于要慎用

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

在这里插入图片描述

11.Like查询要注意

EXPLAIN SELECT * FROM users WHERE name like '%admin%';
EXPLAIN SELECT * FROM users WHERE name like '%admin';
EXPLAIN SELECT * FROM users WHERE name like 'admin%';

在这里插入图片描述

12.字符类型加 ''

EXPLAIN SELECT * FROM users WHERE name = 123;
EXPLAIN SELECT * FROM users WHERE name = '123';

在这里插入图片描述

13.OR改UNION效率高

EXPLAIN SELECT * FROM users WHERE name = '123' OR name = 'admin';
EXPLAIN SELECT * FROM users WHERE name = '123' UNION SELECT * FROM users WHERE name = 'admin';

在这里插入图片描述

EXPLAIN SELECT * FROM users WHERE name = '123' UNION SELECT * FROM users WHERE name = 'admin';

可以看到 OR连接的各条件字段要能用到索引的情况下,将 OR 改为 UNION 改变sql执行计划,从而达到提升SQL性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值