mysql-笔记-命名、索引规范
1 命名规范
普通索引:idx_字段名
唯⼀索引:ux_字段名
所有数据库对象名称必须使⽤⼩写字母并⽤下划线分割
禁⽌使⽤mysql保留关键字 ---如果表名中包含关键字查询时,需要将其有单引号括起来
见名识意,并且最后不要超过32个字符
临时库表以tmp_为前缀并以⽇期为后缀,备份表以bak_为前缀并以⽇期为后缀
所有存储相同数据的列名和列类型必须⼀致--⼀般作为关联列,如果查询时关联列类型不⼀致会⾃动进⾏数据类型隐式转换,会造成列上的索引失效,导致查询效率降低
2 数据库基本设计规范
没有特殊要求下,所有表必须使⽤innodb存储引擎--⽀付事务、⾏级锁、更好的恢复性、⾼并发下性能更好
数据库和表的字符集统⼀使⽤utf8---统⼀字符集可以避免由于字符集转换产⽣的乱码,不同的字符集进⾏⽐较前需要进⾏转换会造成索引失效
所有表和字段都需要添加注释--使⽤comment从句添加表和列的备注进⾏数据字典的维护
尽量控制单表数据量的⼤⼩,建议控制在500万以内,过⼤会造成修改表结构、备份、恢复都会有很⼤的问题。可以⽤历史数据归档应⽤于⽇志数据,分库分表应⽤于业务数据等⼿段
谨慎使⽤mysql分区表--分区表在物理上表现为多个⽂件,在逻辑上表现为⼀个表,跨分区查询效率可能更低,建议采⽤物理分表的⽅式管理⼤数据
尽量做到冷热数据分离,减⼩表的宽度--mysql限制每个表最多存储4096列,并且每⼀⾏数据在⼤⼩不能超过65535字节减少磁盘IO--保证热数据的内存缓存命中率,避免读⼊⽆⽤的冷数,经常⼀起使⽤的列放到⼀个表中避免更多的关联操作。
禁⽌在表中建⽴预留字段--⽆法确认存储的数据类型,对预留字段类型的修改会对表进⾏锁定
禁⽌在数据库中存储图⽚,⽂件等⼤的⼆进制数据---IO操作耗时,通常存储于⽂件服务器,数据库只存储⽂件地址信息
禁⽌在线上做数据库压⼒测试
禁⽌从开发环境、测试环境直接连接⽣成环境数据库
2 数据库字段设计规范
优先选择符合存储需要的最⼩的数据类型-- 字段⼤,建⽴索引空间⼤,IO次数多,索引性能差
  1 将字符串转换成数字类型存储如:IP地址-插⼊数据前先⽤inet_aton把ip地址转为整型,节省空间,显⽰数据时使⽤inet_ntoa把整型ip 地址转为地址显⽰即可
  2 对于⾮负型的数据如⾃增id IP 要优先使⽤⽆符号整型来存储,⽆符号相对于有符号可以多出⼀倍的存储空间
    SIGNED INT -2147483648~2147483647
    UNSIGNED INT 0~4294967295
    VARCHAR(N)中的N代表的是字符数,⽽不是字节数
    使⽤UTF8存储255个汉字 Varchar(255)=765个字节。过⼤的长度会消耗更多的内存
避免使⽤text、blob数据类型,最常见的text类型可以存储64K的数据---可以分离到单独的扩展表中
mysql内存临时表不⽀持text/blob⼤数据类型,如果查询中包含这样的数据,在排序等操作时,就不能使⽤内存临时表,必须使⽤磁盘临时表进⾏。mysql还要进⾏⼆次查询,会使sql性能变得很差,不需要text列的数据时不要对该列进⾏查询
text/blob类型只能使⽤前缀索引,并且text列上是不能有默认值的
避免使⽤enum类型--修改enum值需要使⽤alter语句-enum类型的order by 操作效率低,需要额外操作,禁⽌使⽤数值作为enum的枚举值
尽可能把所有列定义为not null--索引null列需要额外的空间来保存,所以要占⽤更多的空间;进⾏⽐较和计算时要对null值做特别的处理
使⽤timestamp 4个字节或 datetime类型8个字节存储时间
  TIMESTAMP 存储的时间范围 1970-01-01 00:00:01 ~ 2038-01-19-03:14:07。
  TIMESTAMP 占⽤4字节和INT相同,但⽐INT可读性⾼
  超出TIMESTAMP取值范围的使⽤DATETIME类型存储
同财务相关的⾦额数据必须使⽤decimal类型
  ⾮精准浮点:float,double
  精准浮点:decimal
  Decimal类型为精准浮点数,在计算时不会丢失精度。占⽤空间由定义的宽度决定,每4个字节可以存储9位数字,并且⼩数点要占⽤⼀个字节。可⽤于存储⽐bigint更⼤的整型数据。
4 索引设计规范
限制每张表上的索引数量,不超过5个,索引可以增加查询效率,同样也会降低插⼊和更新的效率,有些情况下会降低查询效率
因为mysql优化器在选择如何优化查询时,会根据统⼀信息,对每⼀个可以⽤到的索引来进⾏评估,以⽣成出⼀个最好的执⾏计划,如果同时有很多个索引都可以⽤于查询,就会增加mysql优化器⽣成执⾏计划的时间,同样会降低查询性能
mysql group by order by
禁⽌给表中的每⼀列都建⽴单独的索引---使⽤联合索引查询
每个索引组织表innodb必须有个主键--数据的存储的逻辑顺序和索引的顺序是相同的,每个表都可以有多个索引,但是表的存储顺序只能有⼀种innodb是按照主键索引的顺序来组织表的。
不要使⽤更新频繁的列作为主键,不要使⽤uuid md5 hash 字符串列作为主键--⽆法保证数据的顺序增加
主键建议使⽤⾃增ID值
5 常见索引列建议
出现在select update delete 语句的where 从句中的列
包含在order by  group by  distinct中的字段
多表join的关联列
建⽴联合索引效果更好
6 索引列的顺序 -区分别最⾼的放在联合索引的最左侧,区分度=列中不同值的数量/列的总⾏数
尽量把字段长度⼩的列放在联合索引的左侧
7 避免建⽴冗余索引和重复索引
  重复索引⽰例:primary key(id)、index(id)、unique index(id)
  冗余索引⽰例:index(a,b,c)、index(a,b)、index(a)
8 优先考虑覆盖索引--就是包含了所有查询字段(where select order bjy group by )的索引
避免lnnodb表进⾏索引的⼆次查询
9 索引规范
尽量避免使⽤外键约束,但要在表与表之间的关联键上建⽴索引,外键建议在业务端实现参照完整性
外键会影响⽗表和⼦表的写操作从⽽降低性能
10 数据库开发规范
建议使⽤预编译语句进⾏数据库操作-减少编译所需要的时间,还可以解决动态sql所带来的sql注⼊问题只传参数,⽐传递sql语句更⾼效,相同语句可以⼀次解析,多次使⽤,提⾼处理效率
避免数据类型的隐式转换 id=''
充分利⽤表上已经存在的索引-避免使⽤双%号的查询条件
⼀个sql只能利⽤到复合索引中的⼀列进⾏范围查询-如:有 a,b,c列的联合索引,在查询条件中有a列的范围查询,则在b,c列上的索引将不会被⽤到,在定义联合索引时,如果a列要⽤到范围查的话,就要把a列放到联合索引的右侧
  使⽤left join或 not exists来优化not in操作  因为not in 也通常会使⽤索引失效。
数据库设计进,应要对以后扩展进⾏考虑
程序连接不同的数据库使⽤不同的账号,跨库查询
为数据库迁移和分库分表留出余地
降低业务耦合度
避免权限过⼤⽽产⽣的安全风险
禁⽌使⽤select * 使⽤select 字段查询
禁⽌使⽤不含字段⼀表的insert语句
避免使⽤⼦查询,可以把⼦查询优化为join操作通⽤⼦查询在in⼦句中,且⼦查询中为简单sql进才可以转化为关联查询进⾏优化
⼦查询结果信⽆法使⽤索引,通常⼦查询的结果集会被存储到临时表中,不论是内存临时表还是磁盘临时表都不会存在索引。
避免使⽤JOIN关联太多的表-关联缓存⼤⼩可以由join_buffer_size参数进⾏设置,最多允许关联61个表,建议不超过5个。
减少同数据库的交互次数-批量操作合交多个相同的操作到⼀起,可以提⾼处理效率
对应同⼀列进⾏or判断时,使⽤in代替or,in 的值不要超过500个,可以更有效的利⽤索引,or很少能利⽤到索引
禁使⽤order by rand()进⾏随机排序
where从句中禁⽌对列进⾏函数转换和计算:⽆法使⽤索引
在明显不会有重复值时使⽤union all ⽽不是union
union 会把两个结果集的所有数据放到临时表中后再进⾏去重操作,union all 不会再对结果集进⾏去重操作
拆分复杂的⼤sql为多个⼩sql:⼤sql逻辑上⽐较复杂,需要占⽤⼤量cpu进⾏计算;mysql⼀个sql只能使⽤⼀个cpu进⾏计算,拆分的可能通过并⾏执⾏来提⾼处理效率
11 数据库操作⾏为规范
超100万⾏的批量写操作,要分批多次进⾏操作;⼤批量写操作产⽣⼤量⽇志。特别是对于row格式。
⼤批量修改数据,⼀定是在⼀个事务中进⾏的,这就会造成表中⼤批量数据进⾏锁定,从⽽导致⼤量的阻塞
对于⼤表使⽤pt-online-schema-change修改表结构:避免⼤表修改产⽣的主从延迟,避免在对表字段进⾏修改时进⾏锁表,pt-online-schema-change⾸先建⽴⼀个与原表结构相同的新表,并且在新表上进⾏表结构的修改,然后再把原表中的数据复制到新表中,并在原表中增加⼀些触发器。把原表中新增的数据也复制到新表中,在⾏所有数据复制完成之后,把新表命名成原表,并把原表删除掉。
禁⽌为程序使⽤的账号赋予super权限-只能留给DBA处理问题账号使⽤。
对于程序连接数据库账号,遵循权限最⼩原则