我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL开发规范之我见

短信预约 信息系统项目管理师 报名、考试、查分时间动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL开发规范之我见

  大多数MySQL规范在网上也都能找得到相关的分享,在这里要分享的是老叶个人认为比较重要的,或者容易被忽视的,以及容易被混淆的一些地方。

  1、默认使用InnoDB引擎

  【老叶观点】已多次呼吁过了,InnoDB适用于几乎99%的MySQL应用场景,而且在MySQL 5.7的系统表都改成InnoDB了,还有什么理由再死守MyISAM呢。

  此外,频繁读写的InnoDB表,一定要使用具有自增/顺序特征的整型作为显式主键。

  【参考】:[MySQL FAQ]系列 — 为什么InnoDB表要建议用自增列做主键。

  2、字符集选择utf-8

  【老叶观点】若为了节省磁盘空间,则建议选择latin1。建议选择utf-8通常是为了所谓的“通用性”,但事实上用户提交的utf-8数据也一样可以以latin1字符集存储。

  用latin1存储utf-8数据可能遇到的麻烦是,如果有基于中文的检索时,可能无法100%准确(老叶亲自简单测试常规的中文完检索全不是问题,也就是一般的中文对比是没问题的)。

  用latin1字符集存储utf-8数据的做法是:在web端(用户端)的字符集是utf-8,后端程序也采用utf-8来处理,但 character_set_client、character_set_connection、character_set_results、character_set_database、character_set_server 这几个都是 latin1,且数据表、字段的字符集也是latin1。或者说数据表采用latin1,每次连接后执行 SET NAMES LATIN1 即可。

  【参考】:小谈MySQL字符集。

  3、InnoDB表行记录物理长度不超过8KB

  【老叶观点】InnoDB的data page默认是16KB,基于B+Tree的特点,一个data page中需要至少存储2条记录。因此,当实际存储长度超过8KB(尤其是TEXT/BLOB列)的大列(large column)时会引起“page-overflow存储”,类似ORACLE中的“行迁移”。

  因此,如果必须使用大列(尤其是TEXT/BLOB类型)且读写频繁的话,则最好把这些列拆分到子表中,不要和主表放在一起存储。如果不太频繁,可以考虑继续保留在主表中。

  当然了,如果将 innodb_page_size 选项修改成 8KB,那么行记录物理长度建议不超过4KB。

  【参考】:[MySQL优化案例]系列 — 优化InnoDB表BLOB列的存储效率。

  4、是否使用分区表

  【老叶观点】在一些使用分区表后明显可以提升性能或者运维便利性的场景下,还是建议使用分区表。

  比如老叶就在zabbix的数据库采用TokuDB引擎的前提下,又根据时间维度使用了分区表。这样的好处是保证zabbix日常应用不受到影响前提下,方便管理员例行删除过去数据,只需要删除相应分区即可,不需再执行一个非常慢的DELETE而影响整体性能。

  【参考】:迁移Zabbix数据库到TokuDB。

  5、是否使用存储过程、触发器

  【老叶观点】在一些合适的场景下,用存储过程、触发器也完全没问题。

  我们以前就是利用存储完成游戏业务逻辑处理,性能上不是问题,而且一旦需求有变更,只需修改存储过程,变更代价很低。我们还利用触发器维护一个频繁更新的表,对这个表的所有变更都将部分字段同步更新到另一个表中(类似物化视图的变相实现),也不存在性能问题。

  不要把MySQL的存储过程和触发器视为洪水猛兽,用好的话,没有问题的,真遇到问题了再优化也不迟。另外,MySQL因为没有物化视图,因此视图能不用就尽量少用吧。

  6、选择合适的类型

  【老叶观点】除了常见的建议外,还有其他几个要点:

  6.1、用INT UNSIGNED存储IPV4地址,用INET_ATON()、INET_NTOA()进行转换,基本上没必要使用CHAR(15)来存储。

  6.2、枚举类型可以使用ENUM,ENUM的内部存储机制是采用TINYINT或SMALLINT(并非CHAR/VARCHAR),性能一点都不差,记住千万别用CHAR/VARCHAR 来存储枚举数据。

  6.3、还个早前一直在传播的“常识性误导”,建议用TIMESTAMP取代DATETIME。其实从5.6开始,建议优先选择DATETIME存储日期时间,因为它的可用范围比TIMESTAMP更大,物理存储上仅比TIMESTAMP多1个字节,整体性能上的损失并不大。

  6.4、所有字段定义中,默认都加上NOT NULL约束,除非必须为NULL(但我也想不出来什么场景下必须要在数据库中存储NULL值,可以用0来表示)。在对该字段进行COUNT()统计时,统计结果更准确(值为NULL的不会被COUNT统计进去),或者执行 WHERE column IS NULL 检索时,也可以快速返回结果。

  6.5、尽可能不要直接 SELECT * 读取全部字段,尤其是表中存在 TEXT/BLOB 大列的时候。可能本来不需要读取这些列,但因为偷懒写成 SELECT * 导致内存buffer pool被这些“垃圾”数据把真正需要缓冲起来的热点数据给洗出去了。

  8、关于索引

  【老叶观点】除了常见的建议外,还有几个要点:

  8.1、超过20个长度的字符串列,最好创建前缀索引而非整列索引(例如:ALTER TABLE t1 ADD INDEX(user(20))),可以有效提高索引利用率,不过它的缺点是对这个列排序时用不到前缀索引。前缀索引的长度可以基于对该字段的统计得出,一般略大于平均长度一点就可以了。

  8.2、定期用 pt-duplicate-key-checker 工具检查并删除重复的索引。比如 index idx1(a, b) 索引已经涵盖了 index idx2(a),就可以删除 idx2 索引了。

  8.3、有多字段联合索引时,WHERE中过滤条件的字段顺序无需和索引一致,但如果有排序、分组则就必须一致了。

  比如有联合索引 idx1(a, b, c),那么下面的SQL都可以完整用到索引


SELECT ... WHERE b = ? AND c = ? AND a = ?;  --注意到,WHERE中字段顺序并没有和索引字段顺序一致
SELECT ... WHERE b = ? AND a = ? AND c = ?;
SELECT ... WHERE a = ? AND b IN (?, ?) AND c = ?;
SELECT ... WHERE a = ? AND b = ? ORDER BY c;
SELECT ... WHERE a = ? AND b IN (?, ?) ORDER BY c;
SELECT ... WHERE a = ? ORDER BY b, c;
SELECT ... ORDER BY a, b, c;  -- 可利用联合索引完成排序

  而下面几个SQL则只能用到部分索引


SELECT ... WHERE b = ? AND a = ?;   -- 只能用到 (a, b) 部分
SELECT ... WHERE a IN (?, ?) AND b = ?;   -- 只能用到 (a, b) 部分
SELECT ... WHERE a = ? AND c = ?;   -- 只能用到 (a) 部分
SELECT ... WHERE a = ? AND b IN (?, ?);    -- 只能用到 (a, b) 部分
SELECT ... WHERE (a BETWEEN ? AND ?) AND b = ?;   -- 只能用到 (a) 部分,注意BETWEEN和IN的区别
SELECT ... WHERE a = ? AND (b BETWEEN ? AND ?) AND c = ?;    -- 只能用到 (a, b) 部分

  下面的几个SQL完全用不到该索引


SELECT ... WHERE b = ?;
SELECT ... WHERE b = ? AND c = ?;
SELECT ... WHERE b = ? AND c = ?;
SELECT ... ORDER BY b;
SELECT ... ORDER BY b, a;

  从上面的几个例子就能看的出来,以往强调的WHERE条件字段顺序要和索引顺序一致才能使用索引的 “常识性误导” 无需严格遵守。

  此外,有些时候查询优化器指定的索引或执行计划可能并不是最优的,可以手工指定最优索引,或者修改session级的 optimizer_switch 选项,关闭某些导致效果反而更差的特性(比如index merge通常是好事,但也遇到过用上index merge后反而更差的,这时候要么强制指定其中一个索引,要么可以临时关闭 index merge 特性)。

  9、其他

  9.1、哪怕是基于索引的条件过滤,如果优化器意识到总共需要扫描的数据量超过30%时(ORACLE里貌似是20%,MySQL目前是30%,没准以后会调整),就会直接改变执行计划为全表扫描,不再使用索引。

  9.2、多表JOIN时,要把过滤性最大(不一定是数据量最小哦,而是只加了WHERE条件后过滤性最大的那个)的表选为驱动表。此外,如果JOIN之后有排序,排序字段一定要属于驱动表,才能利用驱动表上的索引完成排序。

  9.3、绝大多数情况下,排序的大家通常要来的更高,因此如果看到执行计划中有 Using filesort,优先创建排序索引吧。

  9.4、利用 pt-query-digest 定期分析slow query log,并结合 Box Anemometer 构建slow query log分析及优化系统。

  【参考】:[MySQL FAQ]系列 — EXPLAIN结果中哪些信息要引起关注。

  备注:若无特别说明,以上规范建议适用于MySQL 5.6及之前的版本。5.7及之后的版本可能会有些变化,个别规范建议需要相应调整。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL开发规范之我见

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

MySQL开发规范之我见

大多数MySQL规范在网上也都能找得到相关的分享,在这里要分享的是老叶个人认为比较重要的,或者容易被忽视的,以及容易被混淆的一些地方。1、默认使用InnoDB引擎【老叶观点】已多次呼吁过了,InnoDB适用于几乎99%的MySQL应用场景,
2022-05-18

java开发规范

所有的程序开发手册都包含了各种规则。一些习惯自由程序人员可能对这些规则很不适 应,但是在多个开发人员 共同写作的情况下,这些规则是必需的。这不仅仅是为了开 发效率来考虑,而且也是为了后期维护考虑。 命名规范 定义这个规范的目的是让项目中所有
2023-06-03

Java开发之代码规范详解

Java开发中所要遵守的编码规范大体上有如下7点。命名规范、注释规范、缩进排版规范、文件名规范、声明规范、语句规范以及编程规范。【推荐学习:java视频教程】1.命名规范(1)所有的标示符都只能用ASCⅡ字母(A-Z或a-z)、数字(0-9)和下划线“_”。(
Java开发之代码规范详解
2021-07-11
2024-04-02

专业级的MySQL开发设计规范及SQL编写规范

在团队开发过程中为了项目的稳定,代码的高效,管理的便捷制定内部种开发设计规范是必不可少的, 这里分享一份我们定义MySQL开发设计规范包括表设计规范,字段设计规范,SQL编写规范 数据库对象命名规范 数据库对象 命名规范的对象是指数据库SC
2022-05-20

PHP开发规范与PSR4命名空间规范

引言:PHP作为一种广泛应用的编程语言,在开发过程中遵守规范是非常重要的,不仅可以提高代码的可读性和可维护性,还能提高团队协作效率。在本文中,我们将探讨PHP开发规范以及PSR-4命名空间规范,并且提供一些具体的代码示例。一、PHP开发规范
2023-10-21

JAVA开发ORACLE的规范

原文:https://blog.51cto.com/15057847/2650042
JAVA开发ORACLE的规范
2017-08-06

MySQL开发规范与使用技巧总结

命名规范1.库名、表名、字段名必须使用小写字母,并采用下划线分割。a)MySQL有配置参数lower_case_table_names,不可动态更改,Linux系统默认为 0,即库表名以实际情况存储,大小写敏感。如果是1,以小写存储,大小写不敏感。如果是2,以
2018-02-06

小程序开发总结之模块化开发流程规范

模块化开发是指将一个系统或者一个项目按照功能或者业务逻辑进行划分,每个功能或者业务逻辑都被封装成一个独立的模块,模块之间通过接口进行通信和交互。小程序的开发也可以采用模块化开发的方式,下面是小程序开发中的模块化开发流程规范:1. 划分模块:
2023-10-12

mongodb开发规范有哪些

1. 命名规范:- 集合(Collection)名应使用小写字母和下划线组成,如:users, orders。- 字段(Field)名应使用小写字母和下划线组成,如:first_name, last_name。- 使用有意义的名称,避免使用
2023-09-04

python 开发规范 预览版

本文主要参考 pep8和jumpserver开发规范,结合实际,进行修改,欢迎提出修改意见。代码检查工具pylintpycharm --> code --> Reformat Code 格式化当前文件代码格式pycharm --> 右击项
2023-01-31

编程热搜

目录