MySQL的优化问题

**索引:** 
提高城查询速度
提高排序速度: 假设磁盘上的数据没顺序,但是btree树是有规律的,沿着树来找是有序的,比如身高是没有序的,但是座位是有序的,按照座位来对身高排序
提高分组统计,先排序再分组也是会更快的

左前缀索引

分析语句的索引
explain 解析 + 语句 ,就能解析一个语句的信息,type:range 用了range索引
key_len:4  4个列都用上了(查询用的列数)
mysql5.7  如果group by c2,c3的话,select只能用 c2,c3 或者avg,sum(xx)这些函数
语法比较严格
多列索引,从左到右(左前缀索引),中间断了或者like了就会没有用
'''
'''
有商品表,有主键 good_id,栏目列cat_id,价格price, 在价格列上已经加了索引,但是按价格查询还是很慢,问 可能是什么原因怎么解决

答: 在实际场景中,一个电商网站的商品分类很多,直接在所有产品中,按价格查商品是极少的,一般客户都来到分类下,然后再查
(按价格查询意义不大,用户通常先找产品,所以产品+价格才有意义)
可以在网站上统计一下购物的习惯,查一下日志
改正:去掉单独的price列的索引,加(cat_id,price)复合索引再查询

如果根据日志统计,发现很多人这样子查,电脑--品牌--价格  index(cat_id,brand_id,price) 

聚簇索引和非聚簇索引

分别对应InnoDB和myisam引擎
myisam 的索引二叉树是一个单独的文件,先到树上找索引,再拿着索引去找数据,就是回行. 它是非聚簇索引
myisam的索引树都是独立的,myisam指向行在磁盘上的位置

聚簇索引:
InnoDB 的树是不一样的,它的叶子比较大,数据直接放在叶子底下,你找到叶子节点的时候,数据就拿到了
除主键索引存放数据,二级索引放的是主键的索引,次级索引指向对主键的引用
1.不需要回行
2.如果主键数据无规律,会造成频繁的页分裂,因为要保持btree的规律,就会导致主键索引带着笨重的数据在不同的页面

InnoDB聚簇索引,乱序插入后里面也是有序的,因为索引树是有规律的
固态硬盘和内存支持随机读写

索引覆盖

索引覆盖 是指 如果查询的列刚好是索引的一部分,那么查询只需要在索引文件上进行,不需要回行到硬盘在找数据
这种查询非常快,称为'索引覆盖'

myisam最为典型,select name from xxx where id>5,先到索引树上查id拿到567,然后再回行,
找索引很快,回行就很慢,所以mysql就是尽量要少的在磁盘上操作
如果id和name是复合索引,就不需要回行了
如果和没有复合索引,就需要回行
用explain 查看,可以看到extra : using index

show profiles 性能分析工具,使用set profiling=1

理想的索引

1.查询频繁 :如果数据不查,加索引就没有意义
2.区分度高  :100w用户,性别基本上男/女各为50w,区分度就低,查询也没意义
3.长度小
4.尽量能覆盖常用查询字段

索引长度直接影响索引文件的大小,影响增删改的速度,并间接影响查询速度(占用内存多)

针对列中的值:从左往右截取部分,来建索引
1.截的越短,重复°越高,区分度越小,索引效果越不好
2.截的越长,重复度越低,区分度越高,索引效果越好,但带来的影响也越大 增删改变慢,并间接影响查询速度
所以,要在 区分度+长度 两者上取得一个平衡
惯用手法:  截取不同长度,并测试其区分度
相除

去重:distinct,  select distinct name from table

sql语句的优化

1.sql语句的时间花在哪?
	等待时间和执行时间,
这两个时间并不是孤立的,如果单挑语句执行的快了,对其他语句的锁定也就少了.所以,我们来分析如何降低执行时间
单条快,其他等待的就少了
2.sql语句的执行时间花在哪?
	a.查找:沿着索引查找,慢者可能全表索引
	b.取出:查到行后,把数据取出来(sending data)
3.如何查询快?
	a.查询的快:联合索引的顺序,区分度,长度
	b.取的快:索引覆盖
	c.传输的少,更少的行和列
4.切分查询
	按数据拆成多次
	例子: 插入10000行数据,每1000条为单位来进行查询
	分解查询,按逻辑把多表连接查询分成多个简单sql
	sql语句太长未必好,高效才是最重要的
	三表以上的联查,可能意味着表设置的不太好
5.sql的优化思路
答: 不查---少查---高效的查
不查:通过业务逻辑来计算 ,比如一些不重要但是要有的数据,可以通过之前的数据来推算,不用追求绝对的精准. 比如百度搜索一个词,它会告诉你约多少个结果,它肯定也不会去查数据库真的有多少个结果
少查,尽量精准数据,少取行,比如新闻网站,评论内容等,一般一次区10-30条左右
必须要查就尽量在索引上查询行,最好就走索引覆盖
取的时候取尽量少的列,少用 *

limit和翻页优化

limit offset N ,当offset非常大时,效率极低
原因是mysql并不是跳过offset行,然后单取N行,而是取offset+N行,返回放弃前offset行,返回N行
效率较低,当offset越大时,效率越低

优化方法:
1.从业务上去解决
	办法:不允许翻过100页,比如百度,一般翻页到70页左右,没人那么无聊翻那么多页的
2.必须得查:不用offset,用条件查询
select id,name from table where id>500000 limit 10
但是id不能断,用逻辑删除
3.必须得删:
	用索引覆盖+延时加载
	where id>10000000 limit 0,3
	先找id,然后再找数据,当成一张临时表

最重要的 还是不要脱离实际的业务场景

mysql主从

MySQL主从复制(Master-Slave)实践 - 知其然,后知其所以然 - 博客园  https://www.cnblogs.com/gl-developer/p/6170423.html
主服务器:
开启二进制日志
配置唯一的server-id
获得master二进制日志文件名及位置
创建一个用于slave和master通信的用户账号
从服务器:
配置唯一的server-id
使用master分配的用户账号读取master二进制日志
启用slave服务

b站上有一个视频讲的挺好 https://www.bilibili.com/video/av24302299/?p=12
分布式的环境下, MySQL和Redis如何保持数据的一致性? - 知乎 https://www.zhihu.com/question/36413559

你可能感兴趣的:(数据库)