MySQL 严格规范及超强优化

先发布, 之后慢慢完善!!!

1. MySQL 严格规范

MySQL 是一个关系型数据库管理系统, 每个项目都需要数据库, 为了方便性强, 易懂性高, 维护性好, 操作流畅, 最主要的是出错性少, 就需要一套可靠的规范来掌握.

1.1 数据库规范

数据库规范是 MySQL 规范的开始

1.1.1 数据库命名规范

  1. 数据库对象名称必须使用小写字母, 并每个字母或单词之间必须用下划线分割.
  2. 数据库对象名称必须禁止使用 MySQL 保留的关键字以及开发环境的关键字. (若用, 需要用 `` 这个符号括起来, 这样会带来开发过程中不必要的麻烦.)
  3. 数据库对象名称命名必须要做到见名识意.
  4. 数据库对象名称的长度一定不能超过 32 个字符.

1.1.2 数据库设计规范

  1. 数据中有中文, 尤其是 emoji , 数据库的字符集必须使用 utf8mb4. 若数据中全是英文, 这时使用 utf8mb4 和 utf8 是一样的.
  2. 禁止在数据库中存储图片, 文件等大的二进制数据.
    通常文件很大, 会短时间内造成数据量快速增长, 数据库进行数据库读取时, 通常会进行大量的随机 IO 操作, 文件很大时, IO 操作很耗时, 通常存储于文件服务器, 数据库只存储文件地址信息.
  3. 禁止在线上做数据库压力测试.
  4. 禁止从开发环境,测试环境直接连接生成环境数据库.

1.2 表规范

数据库中表规范是 MySQL 规范的第二类

1.2.1 数据库中表命名规范

  1. 表对象名称必须使用字母, 并每个字母或单词之间必须用下划线分割.
  2. 表对象名称必须禁止使用 MySQL 保留的关键字以及开发环境的关键字. (若用, 需要用 `` 这个符号括起来, 这样会带来开发过程中不必要的麻烦.)
  3. 表对象名称命名必须要做到见名识意.
  4. 表对象名称的长度一定不能超过 32 个字符.
  5. 临时表对象命名必须以 tmp_ 为前缀并以日期或时间戳为后缀.
  6. 备份表对象命名必须以 bak_ 为前缀并以日期或时间戳为后缀.

1.2.2 数据库中表设计规范

  1. 若无特殊要求或者情况, 所有表必须使用 Innodb 存储引擎.
    特殊要求便是 Innodb 无法满足的功能, 例如: 列存储, 存储空间数据等. Innodb 除了支持事务外, 还支持行级锁, 更好的恢复性, 高并发下性能更好.
  2. 数据中有中文, 尤其是 emoji , 表的字符集必须使用 utf8mb4. 若数据中全是英文, 这时使用 utf8mb4 和 utf8 是一样的, 且和数据库的字符集高度统一. (这个和数据库的要求是一样的)
    统一字符集, 兼容性更好, 可以避免由于字符集转换产生的乱码, 不同的字符集进行比较前进行转换会造成索引失效.
  3. 所有单表数据量的大小, 必须控制在 500 万行以内. 若超过这个数量, 必须采用历史数据归档, 分库分表等手段来控制数据量的大小.
    500 万行不是数据库的限制, 过大会造成修改表的结构, 备份, 恢复等都会有很大的问题, 可以用历史数据归档 (应用于日志数据), 分库分表 (应用于业务数据) 等手段来控制数据量的大小.
  4. 严禁使用 MySQL 分区表.
    分区表在物理上表现为多个文件,在逻辑上表现为一个表, 谨慎选择分区键,跨分区查询效率可能更低, 建议采用物理分表的方式管理大数据.
  5. 尽最大努力做到零热数据分离, 较少表的宽度.
    MySQL 限制每个表最多存储 4096 列,并且每一行数据的大小不能超过 65535 字节, 减少磁盘IO, 保证热数据的内存缓存命中率 (表越宽, 把表装载进内存缓冲池时所占用的内存也就越大, 也会消耗更多的 IO.) 更有效的利用缓存, 避免读入无用的冷数据经常一起使用的列放到一个表中 (避免更多的关联操作).
  6. 禁止在表中建立预留字段.
    预留字段的命名很难做到见名识义, 预留字段无法确认存储的数据类型, 所以无法选择合适的类型, 对预留字段类型的修改, 会对表进行锁定.
  7. 所有表都必须添加注释.
    使用 comment 从句添加表的备注, 从一开始就进行数据字典的维护.

1.3 属性规范

数据库中表规范是 MySQL 规范的第三类

1.3.1 数据库中表中属性命名规范

  1. 属性名称必须禁止使用 MySQL 保留的关键字以及开发环境的关键字. (若用, 需要用 `` 这个符号括起来, 这样会带来开发过程中不必要的麻烦.)
  2. 属性名称命名必须要做到见名识意.
  3. 属性名称的长度一定不能超过 11 个字符.
    当导出 DBase文件 (*.dbf) 文件的时候, 该文件会自动将该表的所有超过 11 个字母的字段截取前 11 个字母作为该列新的字段名.

1.3.2 数据库中表中属性设计规范

  1. 所有存储相同的数据表中的属性和属性类型必须一致.
    作为关联列, 若查询时关联列的类型不一致会自动进行数据类型隐式转换, 会造成列上的索引失败, 导致查询效率降低.
  2. 优先选择符合存储需要的最小的数据类型.
    列的字段越大, 建立索引时所需要的空间也就越大, 这样一页中所能存储的索引节点的数量也就越少也越少, 在遍历时所需要的 IO 次数也就越多, 索引的性能也就越差.
            1)将字符串转换成数字类型存储
    如: 将 IP 地址转换成整形数据. MySQL 提供了两个方法来处理 IP 地址: inet_aton
    把 IP 转为无符号整型 (4-8位) inet_ntoa 把整型的 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 个字节. 过大的长度会消耗更多的内存.
  3. 避免使用 TEXT、BLOB 数据类型, 最常见的 TEXT 类型可以存储 64k 的数据.
            1)建议把 BLOB 或是 TEXT 列分离到单独的扩展表中.
            MySQL 内存临时表不支持 TEXT、BLOB 这样的大数据类型, 如果查询中包含这样的数据, 在排序等操作时, 就不能使用内存临时表, 必须使用磁盘临时表进行.
            而且对于这种数据,MySQL 还是要进行二次查询,会使sql性能变得很差,但是不是说一定不能使用这样的数据类型.
            如果一定要使用,建议把 BLOB 或是 TEXT 列分离到单独的扩展表中, 查询时一定不要使用 select * 而只需要取出必要的列, 不需要 TEXT 列的数据时不要对该列进行查询.
            2)TEXT 或 BLOB 类型只能使用前缀索引.
            因为 MySQL 对索引字段长度是有限制的, 所以TEXT类型只能使用前缀索引, 并且 TEXT 列上是不能有默认值的.
  4. 避免使用 ENUM 类型.
    修改 ENUM 值需要使用 ALTER 语句.
    ENUM 类型的 ORDER BY 操作效率低, 需要额外操作.
    禁止使用数值作为 ENUM 的枚举值.
  5. 能定义成 NOT NULL 的一定定义成 NOT NULL.
    索引列需要额外的空间来保存, 所以要占用更多的空间.
    进行比较和计算时要对值做特别的处理.
  6. 使用 TIMESTAMP (4个字节) 或 DATETIME 类型 (8个字节) 存储时间.
    TIMESTAMP 占用 4 字节和 INT 相同,但比 INT 可读性高.
    超出 TIMESTAMP 取值范围的使用 DATETIME 类型存储.
    经常会有人用字符串存储日期型的数据 (不正确的做法):
            缺点1: 无法用日期函数进行计算和比较.
            缺点2: 用字符串存储日期要占用更多的空间.
  7. 同财务相关的金额类数据必须使用 decimal 类型.
    非精准浮点: float, double.
    精准浮点: decimal.
    Decimal 类型为精准浮点数,在计算时不会丢失精度。占用空间由定义的宽度决定,每 4 个字节可以存储 9 位数字,并且小数点要占用一个字节。可用于存储比 bigint 更大的整型数据.

1.3 索引规范

数据库中表规范是 MySQL 规范的第四类

1.3.1 索引命名规范

  1. 索引名称必须是 数据库名_表名_字段名
  2. 索引名称命名必须要做到见名识意.
  3. 索引名称的长度一定不能超过 64 个字符.

1.3.2 索引设计规范

  1. 限制每张表上的索引数量, 建议单张表索引不超过 5 个.
    索引并不是越多越好, 索引可以提高效率同样可以降低效率.
    索引可以增加查询效率, 但同样也会降低插入和更新的效率, 甚至有些情况下会降低查询效率.
    因为 MySQL 优化器在选择如何优化查询时, 会根据统一信息, 对每一个可以用到的索引来进行评估, 以生成出一个最好的执行计划, 如果同时有很多个索引都可以用于查询, 就会增加MySQL 优化器生成执行计划的时间, 同样会降低查询性能.
  2. 禁止给表中的每一列都建立单独的索引.
    5.6 版本之前, 一个 SQL 只能使用到一个表中的一个索引, 5.6 以后, 虽然有了合并索引的优化方式, 但是还是远远没有使用一个联合索引的查询方式好.
  3. 每个 Innodb 表必须有个主键.
    Innodb 是一种索引组织表: 数据的存储的逻辑顺序和索引的顺序是相同的.
    每个表都可以有多个索引, 但是表的存储顺序只能有一种 Innodb 是按照主键索引的顺序来组织表的.
    不要使用更新频繁的列作为主键, 不适用多列主键 (相当于联合索引) 不要使用 UUID、MD5、HASH、字符串列作为主键 (无法保证数据的顺序增长)
    主键建议使用自增ID值.
    主键含于唯一索引, 根据墨菲定律, 只要没有唯一索引, 必然会产生读脏数据.

1.4 数据库 MySQL 开发规范

2. MySQL 优化

2.1 调优手段

调优手段常用的是执行计划 explain

查询会很慢, 执行时间比较久的 MySQL 语句, 找出 MySQL 语句之后, 用到 explain 命令来查看 MySQL 语句的执行计划, 查看该 MySQL 语句有没有使用上了索引, 有没有做全表扫描.

深入了解 MySQL 的基于开销的优化器, 还可以获得很多可能被优化器考虑到的访问策略的细节, 以及当运行 MySQL 语句时哪种策略预计会被优化器采用.

简要解释下 explain 各个字段的含义:

id: 表示 MySQL 执行的顺序的标识,MySQL 从大到小的执行.

select_type: 表示查询中每个 select 子句的类型.

table: 显示这一行的数据是关于哪张表的, 有时不是真实的表名字.

type: 表示 MySQL 在表中找到所需行的方式, 又称 “访问类型”. 常用的类型有: ALL, index, range, ref, eq_ref, const, system, NULL (从左到右,性能从差到好)

possible_keys: 指出 MySQL 能使用哪个索引在表中找到记录, 查询涉及到的字段上若存在索引, 则该索引将被列出, 但不一定被查询使用.

Key: key列显示MySQL实际决定使用的键 (索引), 如果没有选择索引, 键是NULL.

key_len: 表示索引中使用的字节数, 可通过该列计算查询中使用的索引的长度 (key_len 显示的值为索引字段的最大可能长度, 并非实际使用长度, 即 key_len 是根据表定义计算而得, 不是通过表内检索出的)

ref: 表示上述表的连接匹配条件, 即哪些列或常量被用于查找索引列上的值.

rows: 表示 MySQL 根据表统计信息及索引选用情况, 估算的找到所需的记录所需要读取的行数, 理论上行数越少, 查询性能越好

Extra: 该列包含 MySQL 解决查询的详细信息

EXPLAIN的特性:

EXPLAIN 不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况

EXPLAIN 不考虑各种 Cache

EXPLAIN 不能显示 MySQL 在执行查询时所作的优化工作.

部分统计信息是估算的, 并非精确值.

EXPALIN 只能解释 SELECT 操作, 其他操作要重写为 SELECT 后查看执行计划.

2.2 MySQL 语句优化

2.3 配置优化

2.3.1 基本配置

  1. innodb_buffer_pool_size
    安装完 InnoDB 后第一个应该设置的选项. 缓冲池是数据和索引缓存的地方: 此值越大越好, 这能保证在大多数的读取操作时使用的是内存而不是硬盘. 典型的值是5-6GB (8GB内存), 20-25GB (32GB内存), 100-120GB (128GB内存).

参考网址:
[1]: https://mp.weixin.qq.com/s/lyWTFRu2-iK-starny1_Mg
[2]: https://mp.weixin.qq.com/s/Jq46pmKMVNAL55bm-UyfdA
[3]: https://mp.weixin.qq.com/s/utQVkzIw3OgylGpzA4xyXw

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值