MySQL 的 21 个规范、优化最佳实践!

前言

每一个好习惯都是一笔财富,本文分 SQL 后悔药,SQL 性能优化,SQL 规范优雅三个方向,分享写 SQL 的 21 个好习惯和最佳实践!

写完SQL先explain查看执行计划(SQL性能优化)

日常开发写 SQL 的时候,尽量养成这个好习惯呀:写完 SQL 后,用 explain 分析一下,尤其注意走不走索引。

操作 delete 或者 update 语句,加个 limit(SQL后悔药)

在执行删除或者更新语句,尽量加上 limit,以下面的这条 SQL 为例吧:

delete from euser where age > 30 limit 200;

因为加了 limit 主要有这些好处:

1、降低写错 SQL 的代价,你在命令行执行这个 SQL 的时候,如果不加 limit,执行的时候一个不小心手抖,可能数据全删掉了,如果删错了呢?加了 limit 200,就不一样了。删错也只是丢失 200 条数据,可以通过 binlog 日志快速恢复的。
2、SQL 效率很可能更高,你在 SQL 行中,加了 limit 1,如果第一条就命中目标 return, 没有 limit 的话,还会继续执行扫描表。

3、避免了长事务,delete 执行时,如果 age 加了索引,MySQL会将所有相关的行加写锁和间隙锁,所有执行相关行会被锁住,如果删除数量大,会直接影响相关业务无法使用。
4、数据量大的话,容易把 CPU 打满,如果你删除数据量很大时,不加 limit 限制一下记录数,容易把 cpu 打满,导致越删越慢的。

设计表的时候,所有表和字段都添加相应的注释(SQL规范优雅)

这个好习惯一定要养成啦,设计数据库表的时候,所有表和字段都添加相应的注释,后面更容易维护。

正例:

CREATE TABLE `account` (
 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
 `name` varchar(255) DEFAULT NULL COMMENT '账户名',
 `balance` int(11) DEFAULT NULL COMMENT '余额',
 `create_time` datetime NOT NULL COMMENT '创建时间',
 `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
 PRIMARY KEY (`id`),
 KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

反例:

CREATE TABLE `account` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) DEFAULT NULL,
 `balance` int(11) DEFAULT NULL,
 `create_time` datetime NOT NULL ,
 `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`),
 KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8;

SQL书写格式,关键字大小保持一致,使用缩进。(SQL规范优雅)

正例:

SELECT stu.name, sum(stu.score)FROM Student stuWHERE stu.classNo = '1班'GROUP BY stu.name

反例:

SELECT stu.name, sum(stu.score) from Student stu WHERE stu.classNo = '1班' group by stu.name.

显然,统一关键字大小写一致,使用缩进对齐,会使你的 SQL 看起来更优雅~

INSERT语句标明对应的字段名称(SQL规范优雅)

反例:

insert into Student values ('666','业余草','100');

正例:

insert into Student(student_id,name,score) values ('666','业余草','100');

变更SQL操作先在测试环境执行,写明详细的操作步骤以及回滚方案,并在上生产前review。(SQL后悔药)

  • 变更 SQL 操作先在测试环境测试,避免有语法错误就放到生产上了。
  • 变更 Sql 操作需要写明详细操作步骤,尤其有依赖关系的时候,如:先修改表结构再补充对应的数据。
  • 变更 Sql 操作有回滚方案,并在上生产前,review 对应变更 SQL。

设计数据库表的时候,加上三个字段:主键,create_time,update_time。(SQL 规范优雅)

反例:

CREATE TABLE `account` (
 `name` varchar(255) DEFAULT NULL COMMENT '账户名',
 `balance` int(11) DEFAULT NULL COMMENT '余额',
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

正例:

CREATE TABLE `account` (
 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
 `name` varchar(255) DEFAULT NULL COMMENT '账户名',
 `balance` int(11) DEFAULT NULL COMMENT '余额',
 `create_time` datetime NOT NULL COMMENT '创建时间',
 `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
 PRIMARY KEY (`id`),
 KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

理由:

1、主键一定要加上的,没有主键的表是没有灵魂的
2、创建时间和更新时间的话,还是建议加上吧,详细审计、跟踪记录,都是有用的。

阿里开发手册也提到这个点,如图

写完 SQL 语句,检查 where,order by,group by后面的列,多表关联的列是否已加索引,优先考虑组合索引。(SQL性能优化)

反例:

正例:

-- 添加索引alter table user add index idx_address_age (address,age)

修改或删除重要数据前,要先备份,先备份,先备份(SQL 后悔药)

如果要修改或删除数据,在执行SQL前一定要先备份要修改的数据,万一误操作,还能吃口后悔药。

where后面的字段,留意其数据类型的隐式转换(SQL 性能优化)

反例:

//userid 是varchar字符串类型select * from user where userid =123;

正例:

select * from user where userid ='123';

理由:

因为不加单引号时,是字符串跟数字的比较,它们类型不匹配,MySQL 会做隐式的类型转换,把它们转换为浮点数再做比较,最后导致索引失效。

尽量把所有列定义为 NOT NULL(SQL 规范优雅)

NOT NULL 列更节省空间,NULL 列需要一个额外字节作为判断是否为 NULL 的标志位。
NULL 列需要注意空指针问题,NULL 列在计算和比较的时候,需要注意空指针问题。

修改或者删除SQL,先写WHERE查一下,确认后再补充 delete 或 update(SQL后悔药)
尤其在操作生产的数据时,遇到修改或者删除的 SQL,先加个 where 查询一下,确认 OK 之后,再执行 update 或者 delete 操作。

减少不必要的字段返回,如使用select <具体字段> 代替 select * (SQL性能优化)

反例:

select * from employee;

正例:

select id,name from employee;

理由:

节省资源、减少网络开销。
可能用到覆盖索引,减少回表,提高查询效率。

所有表必须使用Innodb存储引擎(SQL规范优雅)

Innodb 支持事务,支持行级锁,更好的恢复性,高并发下性能更好,所以呢,没有特殊要求(即 Innodb 无法满足的功能如:列存储,存储空间数据等)的情况下,所有表必须使用 Innodb 存储引擎。

数据库和表的字符集统一使用 UTF8(SQL规范优雅)

统一使用 UTF8 编码

  • 可以避免乱码问题
  • 可以避免,不同字符集比较转换,导致的索引失效问题

如果是存储表情的,可以考虑 utf8mb4。

尽量使用 varchar 代替 char。(SQL 性能优化)

反例:

`deptName` char(100) DEFAULT NULL COMMENT '部门名称'

正例:

`deptName` varchar(100) DEFAULT NULL COMMENT '部门名称'

理由:

因为首先变长字段存储空间小,可以节省存储空间。

如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。 (SQL规范优雅)
这个点,是阿里开发手册中,Mysql 的规约。你的字段,尤其是表示枚举状态时,如果含义被修改了,或者状态追加时,为了后面更好维护,需要即时更新字段的注释。

SQL修改数据,养成begin + commit 事务的习惯;(SQL后悔药)

正例:

begin;update account set balance =1000000where name ='业余草';commit;

反例:

update account set balance =1000000where name ='业余草';

索引命名要规范,主键索引名为 pk_ 字段名;唯一索引名为 uk _字段名 ; 普通索引名则为 idx _字段名。(SQL规范优雅)
说明: pk_ 即 primary key;uk _ 即 unique key;idx _ 即 index 的简称。

WHERE从句中不对列进行函数转换和表达式计算

假设 loginTime 加了索引。

反例:

select userId,loginTime from loginuser where Date_ADD(loginTime,Interval 7 DAY) >=now();

正例:

explain select userId,loginTime from loginuser where loginTime >= Date_ADD(NOW(),INTERVAL - 7 DAY);

如果修改更新数据过多,考虑批量进行。

反例:

delete from account limit 100000;

正例:

for each(200次){ delete from account limit 500;}

理由:

  • 大批量操作会会造成主从延迟。
  • 操作会产生大事务,阻塞。
  • 量操作,数据量过大,会把cpu打满。

以上内容希望在读者的编程之路上有所帮助!

到此这篇关于MySQL 的 21 个规范、优化最佳实践!的文章就介绍到这了,更多相关MySQL规范优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL优化必须调整的10项配置

    当我们被人雇来监测MySQL性能时,人们希望我们能够检视一下MySQL配置然后给出一些提高建议.许多人在事后都非常惊讶,因为我们建议他们仅仅改动几个设置,即使是这里有好几百个配置项.这篇文章的目的在于给你一份非常重要的配置项清单. 我们曾在几年前在博客里给出了这样的建议,但是MySQL的世界变化实在太快了!写在开始前-即使是经验老道的人也会犯错,会引起很多麻烦.所以在盲目的运用这些推荐之前,请记住下面的内容: 一次只改变一个设置!这是测试改变是否有益的唯一方法. 大多数配置能在运行时使用SET

  • MySQL 性能优化的最佳20多条经验分享

    当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这些优化技巧对你有用. 1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了. 这里最主要

  • mysql数据库开发规范【推荐】

    最近一段时间一边在线上抓取SQL来优化,一边在整理这个开发规范,尽量减少新的问题SQL进入生产库.今天也是对公司的开发做了一次培训,PPT就不放上来了,里面有十来个生产SQL的案例.因为规范大部分还是具有通用性,所以也借鉴了像去哪儿和赶集的规范,但实际在撰写本文的过程中,每一条规范的背后无不是在工作中有参照的反面例子的.如果时间可以的话,会抽出一部分或分析其原理,或用案例证明. 一. 命名规范 1.库名.表名.字段名必须使用小写字母,并采用下划线分割 (1)MySQL有配置参数lower_cas

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

    1.命名规范 1.库名.表名.字段名必须使用小写字母,并采用下划线分割. a)MySQL有配置参数lower_case_table_names,不可动态更改,linux系统默认为 0,即库表名以实际情况存储,大小写敏感.如果是1,以小写存储,大小写不敏感.如果是2,以实际情况存储,但以小写比较. b)如果大小写混合使用,可能存在abc,Abc,ABC等多个表共存,容易导致混乱. c)字段名显示区分大小写,但实际使⽤用不区分,即不可以建立两个名字一样但大小写不一样的字段. d)为了统一规范, 库名

  • MYSQL 数据库命名与设计规范

    1.设计原则 1) 标准化和规范化 数据的标准化有助于消除数据库中的数据冗余.标准化有好几种形式,但Third Normal Form(3NF)通常被认为在性能.扩展性和数据完整性方面达到了最好平衡.简单来说,遵守3NF 标准的数据库的表设计原则是:"One Fact in One Place"即某个表只包括其本身基本的属性,当不是它们本身所具有的属性时需进行分解.表之间的关系通过外键相连接.它具有以下特点:有一组表专门存放通过键连接起来的关联数据. 举例:某个存放客户及其有关定单的3

  • MySQL数据库命名规范及约定

    一.[操作规范]1. 如无备注,则表中的第一个id字段一定是主键且为自动增长:2. 如无备注,则数值类型的字段请使用UNSIGNED属性:3. 如无备注,排序字段order_id在程序中默认使用降序排列:4. 如无备注,所有字段都设置NOT NULL,并设置默认值:5. 如无备注,所有的布尔值字段,如is_hot.is_deleted,都必须设置一个默认值,并设为0:6. 所有的数字类型字段,都必须设置一个默认值,并设为0:7. 针对varchar类型字段的程序处理,请验证用户输入,不要超出其预

  • 浅谈MySQL中优化sql语句查询常用的30种方法

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from

  • MySQL数据库使用规范总结

    导读: 关于MySQL数据库规范,相信大家多少看过一些文档.本篇文章给大家详细分类总结了数据库相关规范,从库表命名设计规范讲起,到索引设计规范,后面又给出SQL编写方面的建议.相信这些规范适用于大多数公司,也希望大家都能按照规范来使用我们的数据库,这样我们的数据库才能发挥出更高的性能. 关于库: 1.[强制]库的名称必须控制在32个字符以内,英文一律小写. 2.[强制]库的名称格式:业务系统名称_子系统名. 3.[强制]库名只能使用英文字母,数字,下划线,并以英文字母开头. 4.[强制]创建数据

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

    在团队开发过程中为了项目的稳定,代码的高效,管理的便捷制定内部种开发设计规范是必不可少的, 这里分享一份我们定义MySQL开发设计规范包括表设计规范,字段设计规范,SQL编写规范 数据库对象命名规范 数据库对象 命名规范的对象是指数据库SCHEMA.表TABLE.索引INDEX.约束CONSTRAINTS等的命名约定 数据库对象命名原则 命名使用具有意义的英文词汇,词汇中间以下划线分隔 命名只能使用英文字母.数字.下划线 避免用MySQL的保留字如:call.group等 所有数据库对象使用小写

  • MySQL性能优化之max_connections配置参数浅析

    MySQL的max_connections参数用来设置最大连接(用户)数.每个连接MySQL的用户均算作一个连接,max_connections的默认值为100.本文将讲解此参数的详细作用与性能影响. 与max_connections有关的特性 MySQL无论如何都会保留一个用于管理员(SUPER)登陆的连接,用于管理员连接数据库进行维护操作,即使当前连接数已经达到了max_connections.因此MySQL的实际最大可连接数为max_connections+1: 这个参数实际起作用的最大值

  • 老鸟带你开发专业规范的MySQL启动脚本

    每一个合格的Linux运维人员都应该做到熟练或精通Shell脚本编程,因为Shell脚本语言差不多是所有编程语言里最简单的语言,如果Shell脚本不行,意味着运维之路可能还没开始就将要终结.--老男孩老师 #!/bin/bash # chkconfig: 2345 64 36 #配置系统自启动 # description: A very fast and reliable SQL database engine. #########################################

  • 超详细MySQL使用规范分享

    最近涉及数据库相关操作较多,公司现有规范也不是太全面,就根据网上各路大神的相关规范,整理了一些自用的规范用法,万望指正. 数据库环境 dev: 开发环境 开发可读写,可修改表结构.开发人员可以修改表结构,可以随意修改其中的数据但是需要保证不影响其他开发同事. test: 测试环境 开发可读写,开发人员可以通过工具修改表结构. online: 线上环境 开发人员不允许直接在线上环境进行数据库操作,如果需要操作必须找DBA进行操作并进行相应记录,禁止进行压力测试. 重点的问题,各个环境的mysql服

  • MySQL查询优化之explain的深入解析

    在分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.explain 可以帮助我们分析 select 语句,让我们知道查询效率低下的原因,从而改进我们查询,让查询优化器能够更好的工作. 一.MySQL 查询优化器是如何工作的MySQL 查询优化器有几个目标,但是其中最主要的目标是尽可能地使用索引,并且使用最严格的索引来消除尽可能多的数据行.最终目标是提交 SEL

  • MySQL配置文件my.cnf参数优化和中文详解

    Mysql参数优化对于新手来讲,是比较难懂的东西,其实这个参数优化,是个很复杂的东西,对于不同的网站,及其在线量,访问量,帖子数量,网络情况,以及机器硬件配置都有关系,优化不可能一次性完成,需要不断的观察以及调试,才有可能得到最佳效果. 复制代码 代码如下: [client]port = 3306socket = /tmp/mysql.sock [mysqld]port = 3306socket = /tmp/mysql.sock basedir = /usr/local/mysqldatadi

  • MySQL 百万级分页优化(Mysql千万级快速分页)

    以下分享一点我的经验 一般刚开始学SQL的时候,会这样写 复制代码 代码如下: SELECT * FROM table ORDER BY id LIMIT 1000, 10; 但在数据达到百万级的时候,这样写会慢死 复制代码 代码如下: SELECT * FROM table ORDER BY id LIMIT 1000000, 10; 也许耗费几十秒 网上很多优化的方法是这样的 复制代码 代码如下: SELECT * FROM table WHERE id >= (SELECT id FROM

  • Mysql建表与索引使用规范详解

    一. MySQL建表,字段需设置为非空,需设置字段默认值.二. MySQL建表,字段需NULL时,需设置字段默认值,默认值不为NULL.三. MySQL建表,如果字段等价于外键,应在该字段加索引.四. MySQL建表,不同表之间的相同属性值的字段,列类型,类型长度,是否非空,是否默认值,需保持一致,否则无法正确使用索引进行关联对比.五. MySQL使用时,一条SQL语句只能使用一个表的一个索引.所有的字段类型都可以索引,多列索引的属性最多15个.六. 如果可以在多个索引中进行选择,MySQL通常

  • MySQL Order by 语句用法与优化详解

    MySQL Order By keyword是用来给记录中的数据进行分类的.MySQL Order By Keyword根据关键词分类ORDER BY keyword是用来给记录中的数据进行分类的. 复制代码 代码如下: SELECT column_name(s) FROM table_name ORDER BY column_name 例子 SQL创建代码: 复制代码 代码如下: CREATE TABLE IF NOT EXISTS mysql_order_by_test (  uid int

  • MySQL 使用规范总结

    1.必须使用InnoDB存储引擎 有更好的CPU和IO性能,更好的备份和锁表机制,提高统计和调试效率. 另外,作为一 个系统,InnoDB支持多种关键功能,其中最重要的是事务日志和行级锁.事务日志记录真正的数据库事务,但更重要的是数据崩溃恢复和回滚. 基于 InooDB方式的IO,能给予更安全数据保护和更好性能表现.另外,在大多数的情况下,行级锁可以提供更高的并发性能,因为用户只锁定他们正在写的数据,而读数据永远不会被阻塞 . 2.数据表.数据字段必须加入中文注释 方便日后新人小哥,更快理解熟悉

随机推荐