相信大家不管是在面试中,或者是在实际的开发过程中,都有接触过SQL优化相关的事情。之前有看到过类似知识的小伙伴可能能说出点东西来,对于没有涉及过相关知识的伙伴也不用着急,看了这篇,相信也足够你去应对面试或者在实际开发工程中使用了。关注收藏,随时拿出来看看,相信对你会有很大的帮助。当然以下SQL优化策略适用于数据量较大的场景下,如果数据量较小,没必要以此为准,以免画蛇添足。

这里不仅仅针对SQL优化进行归纳和总结,我们从最初的建表,包括建表需要注意的事项以及规约,到最后的SQL语句,包括SQL语句书写需要注意的事项以及对于某些SQL语句的优化这一整个过程做一个系统的总结,当然整个过程都涉及到索引的建立与使用,这个是SQL优化的关键,所以这里我会一共分为三个部分进行总结:建表规范及优化、SQL规范及优化、索引规范及优化。当然有些是建议不作为SQL指定规范,大家适当甄别。

建表规范及优化

  • (1) 库名、表名、字段名均小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用。
  • (2)数据库表、表字段必须加入中文注释。
  • (3)尽量统一使用UTF8字符集,在Mysql中的UTF8并非“真正的UTF-8”,而utf8mb4”才是真正的“UTF-8”,如果需要存储表情,那么选择utf8mb4来进行存储,注意它与utf-8编码的区别。
  • (4)存储引擎必须使用InnoDB,因为InnoDB支持事物、行级锁、并发性能更好,CPU及内存缓存页优化使得资源利用率更高。
  • (5)每张表必须设置一个主键ID,create_time,update_time。且这个主键ID使用自增主键(在满足需要的情况下尽量短),除非在分库分表环境下。
    • InnoDB组织数据的方式决定了需要有一个主键,而且若是这个主键ID是单调递增的可以有效提高插入的性能,避免过多的页分裂、减少表碎片提高空间的使用率。
    • 在分库分表环境下,需要统一来分配各个表中的主键值,从而避免整个逻辑表中主键重复。
  • (6)单表列数目必须小于30,若超过则应该考虑将表拆分。单表列数太多使得Mysql服务器处理InnoDB返回数据之间的映射成本太高。
  • (7)禁止使用外键,如果有外键完整性约束,需要应用程序控制,因为外键会导致表与表之间耦合,UPDATE与DELETE操作都会涉及相关联的表,十分影响SQL的性能,甚至会造成死锁。
  • (8)必须把字段定义为NOT NULL并且提供默认值
    • NULL的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化 ;
    • NULL这种类型Msql内部需要进行特殊处理,增加数据库处理记录的复杂性;
    • 同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多;
    • NULL值需要更多的存储空,无论是表还是索引中每行中的NULL的列都需要额外的空间来标识。不要以为 NULL 不需要空间,比如char(100) 型,在字段建立时,空间就固定了, 不管是否插入值(NULL也包含在内),都是占用 100个字符的空间的,如果是varchar这样的变长字段, null 不占用空间。
  • (9)禁用保留字,如DESC、RANGE、MARCH等,请参考Mysql官方保留字
  • (10)在一些场景下,考虑使用TIMESTAMP代替DATETIME
    • 这两种类型的都能表达"yyyy-MM-dd HH:mm:ss"格式的时间
    • TIMESTAMP只需要占用4个字节的长度,可以存储的范围为(1970-2038)年,在各个时区,所展示的时间是不一样的;
    • DATETIME类型占用8个字节,对时区不敏感,可以存储的范围为(1001-9999)年。
  • (11)尽可能的使用 varchar/nvarchar 代替 char/nchar
    • 因为首先变长字段存储空间小,可以节省存储空间;
    • 对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
  • (12)索引命名要规范
    • 主键索引名为 pk_ 字段名,pk_即primary key;
    • 唯一索引名为 uk _字段名 ,uk_即unique key;
    • 普通索引名则为 idx _字段名,idx_即index 。

SQL规范及优化

SQL防范优化

  • (1)写完SQL先explain查看执行计划,分析一下,尤其注意走不走索引,然后针对性的进行调整优化;
explain SELECT id,name
FROM subactivity where id=22184;
SEQ  id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   1   SIMPLE  subactivity NULL    const   PRIMARY PRIMARY 8   const   1   100 NULL
  • (2)操作delete或者update语句,加个limit,这样可以降低写错SQL的代价

    • 加了limit 1,如果第一条就命中目标return,提高SQL效率, 没有limit的话,就会继续执行扫描表;
    • delete执行时,如果相关字段加了索引,MySQL会将所有相关的行加写锁和间隙锁,所有执行相关行会被锁住,如果删除数量大,会直接影响相关业务无法使用;
    • 删除数据量很大时,不加 limit限制一下记录数,容易把cpu打满,导致越删越慢的。
  • (3)变更SQL操作先在测试环境执行,写明详细的操作步骤以及回滚方案,并在上生产前review。
  • (4)修改或删除重要数据前,要先备份。
  • (5)修改或者删除SQL,先写WHERE查一下,确认后再补充 delete 或 update。

SQL查询优化

  • (1)避免使用select *

    • 使用select * 取出全部列,会让优化器无法完成索引覆盖扫描这类优化,会影响优化器对执行计划的选择,也会增加网络带宽消耗,更会带来额外的I/O,内存和CPU消耗。
  • (2)多表关联查询时,小表在前,大表在后,且使用表的别名

    • 执行 from 后的表关联查询是从左往右执行的(Oracle相反),第一张表会涉及到全表扫描,所以将小表放在前面,先扫小表,扫描快效率较高,在扫描后面的大表,或许只扫描大表的前100行就符合返回条件并return了。
  • (3)调整Where字句中的连接顺序

    • MySQL采用从左往右,自上而下的顺序解析where子句。根据这个原理,应将过滤数据多 的条件往前放,最快速度缩小结果集。
  • (4)用where字句替换HAVING字句。

    • HAVING只会在检索出所有记录之后才对结果集进行过滤
    • where是在聚合前刷选记录,如果能通过where字句限制记录的数目,那就能减少这方面的开销;
    • HAVING中的条件一般用于聚合函数的过滤,除此之外,应该将条件写在where字句中。
  • (5)对于复杂的查询,可以使用中间临时表 暂存数据

  • (6)建议使用union all

    • MySQL通过创建并填充临时表的方式来执行union查询。除非确实要消除重复的行,否则建议使用union all。
    • 如果没有all这个关键词,MySQL会给临时表加上distinct选项,这会导致对整个临时表的数据做唯一性校验,这样做的消耗相当高。
  • (7)拆分复杂SQL为多个小SQL,避免大事务

    • 简单的SQL容易使用到MySQL的QUERY CACHE;
    • 减少锁表时间特别是使用MyISAM存储引擎的表;
    • 可以使用多核CPU。
  • (8)查询数据量大的表 会造成查询缓慢,主要的原因是扫描行数过多。这个时候可以通过程序,分段分页进行查询,循环遍历,将结果合并处理进行展示。

SQL增删改优化

  • (1)如果同时执行大量的插入,建议使用多个值的INSERT语句,这比使用分开INSERT语句快,一般情况下批量插入效率有几倍的差别。
  • (2)命令行修改数据,使用begin + commit 事务。
  • (3)当删除全表中记录时,使用truncate代替delete。
    • 使用delete语句的操作会被记录到undo块中,删除记录也记录binlog,当确认需要删除全表时,会产生很大量的binlog并占用大量的undo数据块,此时既没有很好的效率也占用了大量的资源;
    • 使用truncate替代,不会记录可恢复的信息,数据不能被恢复。也因此使用truncate操作有其极少的资源占用与极快的时间。另外,使用truncate可以回收表的水位,使自增字段值归零。

索引规范及优化

索引建立规范

  • (1)表的主键、外键必须有索引;
  • (2)经常与其他表进行连接的表,在连接字段上应该建立索引;
  • (3)对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
  • (4)尽量使用数字型字段(如性别,男:1 女:2)
    • 若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销;
    • 引擎在处理查询和连接时会 逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

索引失效场景

  • (1)尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
  • (2)尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
  • (3)尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,可以改用union或union all
  • (4)尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。
  • (5)尽量避免使用in 和not in,会导致引擎走全表扫描。如果是连续数值,可以用between代替,如果是子查询,可以用exists代替。
  • (6)尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描。可以将表达式、函数操作移动到等号右侧。
  • (7)当数据量大时,避免使用where 1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描。用代码拼装sql时进行判断,没 where 条件就去掉 where,有where条件就加 and。
  • (8)where条件仅包含复合索引非前置列会导致不会走联合索引。
  • (9)尽量避免隐式类型转换,会造成不使用索引。

最后要说的是,索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

MYSQL专题-绝对实用的MYSQL优化总结相关推荐

  1. MYSQL专题-由简到繁理解索引结构

    大家可能都听过数据库索引,当然作为开发者来说其实大部分时间也用过索引.但是可能有的人知道索引是干什么的,但是对于索引的结构却不是很了解.所以这篇博客我会谈谈对索引结构的一些知识以及分享如何从零开始一层 ...

  2. MYSQL专题-使用Binlog日志恢复MySQL数据

    大家有没有碰到过由于误操作把测试数据库的一张表给删除了,导致测试的数据都被删除了,然后手足无措,测试把你一定数落,顿时感觉自己要死了?今天就教你即使误删了也可以将删除的数据恢复,以后误删再也不用惊吓了 ...

  3. MYSQL专题-MVCC多版本并发控制

    MVCC,全称Multi-Version Concurrency Control,即多版本并发控制.MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内 ...

  4. MYSQL专题-MySQL事务实现原理

    用过事务的伙伴大概都知道它的相关特性主要有四个:原子性(Atomicity),一致性(Consistency),隔离型(Isolation)以及持久性(Durability).今天想跟大家一起研究下事 ...

  5. MYSQL专题-MySQL三大日志binlog、redo log和undo log

    日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息.mysql日志主要包括重做日志(redo log).回滚日志(undo log).二进制日志(bin log).错误日志(err ...

  6. 【MySQL专题】MySQL中一条SQL是如何被执行的?---来自于令狐的独孤九剑

    [MySQL专题]MySQL中一条SQL是如何被执行的? 前言 ​ 大家好,我是令狐,欢迎来到令狐的独孤九剑**[MySQL专题]**这节课跟大家聊一聊MySQL中一条SQL是如何被执行的. MySQ ...

  7. MySQL专题(学会就毕业)

    MySQL专题 0.准备sql 设计一张员工信息表,要求如下: 编号(纯数字) 员工工号 (字符串类型,长度不超过10位) 员工姓名(字符串类型,长度不超过10位) 性别(男/女,存储一个汉字) 年龄 ...

  8. mysql 去掉复合索引_MySQL性能优化[实践篇]-复合索引实例

    上篇文章最后提了个问题 假设某个表有一个**复合索引(c1,c2,c3,c4)**,问以下查询中只能使用该复合索引的c1,c2,c3部分的有那些 1. where c1=x and c2=x and ...

  9. MySQL 5.6 my.cnf配置优化

    MySQL 5.6 my.cnf配置优化 4核 16G Centos6.5 x64 优化后测试结果如下 #mysqlslap #--concurrency=2 #--iterations=1 #--n ...

最新文章

  1. “双轮驱动”突破瓶颈,智源研究院发布“自然语言处理”重大研究方向,携手京东打造联合实验室...
  2. 数学界的隐士:世界上最奇怪的数学天才,被奖励100万却拒领
  3. Unity应用架构设计(7)——IoC工厂理念先行
  4. 重理工c语言实验指导书答案,常熟理工学院 C语言程序设计实验实验指导书及答案...
  5. 电气期刊论文实现:热电联产经济调度【有代码】
  6. boost::sort模块spreadsort 完全排序的数据示例
  7. CF-1023F.Mobile Phone Network(并查集缩点)
  8. 【差分+前缀和】BZOJ1637: [Usaco2007 Mar]Balanced Lineup
  9. elasticsearch api中的Multi Get API操作
  10. mysql数据库sql语句优化
  11. spss相关性分析看结果_spss相关性分析
  12. 【Programming Clip】点分十进制IP和长整型转换
  13. php mysqli分页,PHP使用Mysqli类库实现完美分页效果的方法_PHP
  14. 【C语言】中的stdbool.h头文件
  15. python怎么关闭csv_Python2.7.1:如何打开、编辑和关闭CSV fi
  16. 三星app图标不见了怎么恢复_手机便签的内容不见了怎么恢复?试试这款便签软件的时间轴功能...
  17. 好好编程-物流项目03【GitHub管理】
  18. 数学建模灵敏度分析是什么?为什么获奖论文基本都有!【科研交流】
  19. python读取odb_abaqus通过python从ODB中抽取模型数据和结果数据.pdf
  20. 忘记电脑开机密码怎么办?六种方法教你解决

热门文章

  1. linux kernel的virtual kernel memory layout介绍(aarch64)
  2. 字符串格式化漏洞修改GOT表一例
  3. 图片轮播器,relativelayout,外加textview小结
  4. 【网络安全】简要分析下Chrome-V8-Issue-762874
  5. PsSetCreateProcessNotifyRoutineEx进程监控框架
  6. 【PAT乙级】1008 数组元素循环右移问题 (20 分)
  7. Zookeeper选举机制测试
  8. Mybatis的prefix和suffix使用
  9. java oss 批量传输_初步使用阿里云OSS对象存储功能
  10. 通俗讲解分布式锁,看完不懂算我输