mysql稳定性相关的几个小tips

  1. 浮点数用decimal类型,不要用double和float,因为他俩是近似,不准确。
  2. 状态类型用tinyint。
  3. 时间类型用datetime,不推荐用时间戳timestamp,因为timestamp只到2038年,除非你的业务只能活到2038年,非要用时间戳的话就用bigint来替代timestamp。
  4. 自增主键推荐用bigint,因为业务增长快的话,它范围更大,绝对够你用了。
  5. 比varchar更大的字段,比如text等等,就不推荐用mysql来存储了,这些大字段性能低于varchar,而且占用内存更多。

比如有这样一个表:

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE `LOGS` (
`PP` INT(11) NOT NULL AUTO_INCREMENT,
`ID` INT(11) NOT NULL,
`DAY` VARCHAR(20) NOT NULL,
`VIEW` TEXT NOT NULL,
`SHARE` TEXT NOT NULL,
.........
`FROMFRIENDSHARE` TEXT NOT NULL,
PRIMARY KEY (`PP`),
KEY `ID` (`ID`,`DAY`)
) ENGINE=INNODB

这个设计行为就很颠,推荐改成两个表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
		CREATE TABLE `LOGS` (
`PP` INT(11) NOT NULL AUTO_INCREMENT,
`ID` INT(11) NOT NULL,
`DAY` VARCHAR(20) NOT NULL,
`VIEW` TEXT NOT NULL,
`SHARE` TEXT NOT NULL,
.........

PRIMARY KEY (`PP`),
KEY `ID` (`ID`,`DAY`)
) ENGINE=INNODB

CREATE TABLE `LOGS_T` (
`PP` INT(11) NOT NULL AUTO_INCREMENT,
`FROMFRIENDSHARE` TEXT NOT NULL,
PRIMARY KEY (`PP`),
) ENGINE=INNODB

或者 FROMFRIENDSHARE 直接放云存储里,不香么?
  1. 如果非要用大字段,那么就“压缩存储”或者“单独表存储”,好处是“降低binlog大小”和“降低engine到server的传输”。
  2. 比如一个很大的json如果只是更新一个小value,那么用text的话,性能得不偿失,因为要“读出来再写进去,这里面有大量网络交互,同时还要写到binlog里,有大量性能损耗,还会强制生成硬盘临时表”。
  3. 数据库的字段越简单越好,大小越小,16k索引页就能放越多的索引字段,查起来更快。B+树高降低。
  4. op操作可能会导致抖动和主从延迟,建议放业务低峰期操作。
  5. 大sql会造成脏页,会刷binlog,要避免。
  6. 长事务可能会有很长时间的锁。
  7. 单个数据库实例不要订阅太多东西,比如一个实例上绑了好几个数据传输dts,因为一次数据库的更新变更,可能会binlog爆发好几个,对物理机的网卡会有影响。
  8. 尽量不要用数据库去计算!把计算交给代码去实现。也尽量不要去整体的join。
  9. 数据库字段越精确越好,用where去过滤的话,比如数字的比较成本比字符串的比较成本更低。字符串要进行编码转换且要挨个比对,有一个排序的过程。
  10. 尽量多用组合索引,比如索引 : idx_abc(a,b,c) 能走索引的Case:
    1
    2
    3
    4
       a. where a=1   / where a=1  order by b  /  where a=1 order by b,c  (利用a过滤,b,c排序)
    b. where a=1 and b=1 / where a=1 and b=1 order by c (利用a,b过滤,c排序)
    c. where a=1 and b=1 and c=1
    注意:如果后面的排序需要走到索引,需要保证前面的过滤必须是等值
  11. 唯一键是最好的索引。
  12. 尽量不要用null,因为null的优化很复杂,也会让索引统计变得复杂。而且null占用的空间更多,尽量用0,’’这样的东西。
  13. 不要让索引参与计算。比如 select id from XXX where id+1=5;这句话不会让mysql先算出来id=4,反而会把索引的值都取出来一个一个比对,直到=5,这样会导致全表扫和全索引扫。
  14. 索引是不是越多越好?不是的。很多开发在创建索引时想法很简单,就是希望动态生成SQL时,无论传什么where条件,都可以走到一个对应的索引,创建了一大片索引。但很明显这是一个反面教材,把数据库当成了搜索引擎,这样建索引对数据库来说,基本是个事故现场。原因是:
    1. 因为“当执行DML语句时,除了维护正常的表数据之外,还需要同步更新索引列的数据,索引越多,写放大效应越厉害”。
    2. 索引为了维护其有序性,更新是删除旧值再在对应顺序位置插入新值,如果新插入位置所在的数据块已经写满,那就需要把当前数据块部份内容移动一个新的数据块,再修改前后叶子块甚至是分枝块的链式指针,然后再写入数据,这就是我们前面说的块分裂,块分裂非常影响数据库性能,那么索引越多,也会加大了块分裂的可能性。
    3. MySQL优化器相对其他商业数据库还外于一个很初级的阶段,它每次执行SQL时都会重新生成执行计划,而在生成执行计划时,如果有多个索引可被使用时,这些索引会进入possible_key,然后优化器会对每一个possible_key进行采样并计算数据分布情况,进而最终确认使用哪个真实的索引(key)去执行SQL。
感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------