1.mysql的优化思路从哪些角度可以进行思考?
字段选取:进行节衣缩食,选取最合适的字段属性
索引相关:怎么建立索引?联合索引和覆盖索引?尽量减少回表次数
数据页相关:页分裂,页合并,索引重建
语句相关:使用count(*),使用join的须知,使用group by 和order by 的须知,多用 limit,尽量不使用NOT IN和like语句操作,UNION-ALL代替UNION。
事务相关:比如容易引起锁竞争的行放在事务语句的后面。适当的选取事务隔离级别也对优化有帮助。
分库分表:怎么分库分表?
找到瓶颈所在:查看是什么占用比较高,explain (这个过程都得根据实际去区分了)
2. varchar 与char
参考:https://www.cnblogs.com/chinaxieshuai/p/12711382.html
并不一定都用varchar最好,因为varchar是变长的,因为变长所以可能会因为后续数据变大了导致一个行占用空间增加导致了页分裂。
varchar适用的场景:
- 字符串 列的最大长度比平均长度要大很多;
- 字符串 列的更新很少时,因为没有或很少有内存碎片问题;
- 使用了UTF-8这样复杂的字符集,每个字符都使用不同的字节数进行存储;
varchar的优点:
- 变长的字符串类型,兼容性更好
varchar的缺点:
- 使用varchar可能会产生内存碎片
- varchar会额外需要1到2个字节存储长度信息
- update语句可能会导致页分裂
注意每一个列都可以单独指定他的字符集,如果他没有复杂的中文,可以使用不是UTF8来存储。
varchar会多额外需要1到2个字节存储长度信息,而且update可能会导致也分裂所以定长选择char类型更好一点。
char适用的场景:
- 列的长度为定值时适合适用,比如:MD5密文数据
- 无需额外的内存空间去存储长度信息
- 定长的字符串类型,减少内存碎片
char的缺点:
- 会删除列末尾的空格信息
3.为什么使用count(*)最好?
https://blog.youkuaiyun.com/pmdream/article/details/103680804
如果有计数的需求,最好有个计数表。计数表如果有事务,最好是先插入再更新,影响事务的放后面。
对于 count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。
对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。 (这个1是个数字)也就是count(2)也一样
count(1) 执行得要比 count(主键 id) 快。因为从引擎返回 id 会涉及到解析数据行,以及拷贝字段值的操作。
count(字段)还要判断一下为不为null,然后进行累加。为null不累加。
count(*)是例外,专门做了优化,不取值,count(*)肯定不是null,按行累加。
4. 能不使用order by就不使用
因为分为内存中全字段排序和rowid排序(快速排序),以及如果内存被占用太大会使用归并的文件排序。
5.什么时候使用唯一索引什么时候使用普通索引?
因为唯一索引在更新的时候,要把数据页查出来,看看冲不冲突,然后在更新进去。
所以唯一索引并不能用changebuffer。
所以如果是频繁写入更新的数据库,尽量别使用唯一索引,建立普通索引就好~
更新的时候,如果数据页在内存中,就会直接更新。如果没在内存中,在不影响数据一致性的前提下,
innodb有着更新操作缓存change buffer。
这个缓存的特点,内存中有一份 硬盘中也有一份,是持久化的,
而且查询到这个数据页的时候,会进行吧这个change buffer merge进去,执行merge操作。
(PS:后台线程也会定期的merge这个change buffer到磁盘中)
change buffer 可以减少读磁盘,执行速度会得到很大的提升。
数据读入到内存中占用buffer pool,这种方式可以避免占用内存,提高内存的占用率,因为减少读入内存的次数。
另外:数据从硬盘中读入到内存是随机IO访问,成本很高。
尽量选取普通索引。用业务来保证唯一。
如果更新之后就要查询的记录,应该关闭change buffer。