工做的这些年发现一个比较奇怪的现象就是身边不管是工做十多年的老兵,仍是初级刚入行的程序员,在高谈阔论技术和趋势的时候都是人工智能,大数据,区块链,各类框架,语言,算法,AI,BI,CI,DI…… 等等,却是发现不多有人关注数据库,不知道是由于数据库感受过低端仍是过低调,老是不容易被人提起php
技术就是这样,不太关注的地方就不会重视,越是不被重视的地方,掉进坑里的几率就会越大,因此就在这里给你们简单聊聊在使用数据库过程当中有哪些防掉坑指南,也能够对刚入行的小朋友有一个提醒的做用,万丈高楼平地起,必定要先打好基础再去考虑上层的建筑,不要舍本逐末mysql
本章主要分如下四个小节(预计读完 5 分钟左右):程序员
不少人在开发过程当中不太关注数据库,对于表结构的设计也没什么讲究大多属于“能用就行”,可是根据做者将近十年的开发经验来看的话,只要你是从事 Web 相关领域开发你就没法避免不和数据库打交道,在Web开发中大多功能操做本质上都是对数据库进行操做,无论你用是 Pythod,Java,Ruby 等语言进行 Web 开发,你其实都是在面向数据库进行编程,不少 Web 框架做者为了不程序员接触数据库的相关知识甚至还封装了一层 ORM (Object Relational Mapping 对象关系映射),把数据库当作一个黑盒子,而后经过操做对象的形式来操做数据库面试
虽然某种意义上是简化的开发,对此我是持有保留意见的,由于对于程序员来讲颇有必要了解你的 SQL 语言在数据库是怎么执行的,你不只须要使用 explain 执行计划来查看你的 SQL 是否高效(扫描行数,命中索引,回表,排序等),对比不一样 SQL 的写法外,你还须要知道如何使用 show index 来查看你的索引是否高效(经过 Cardinality 由数据库评估),这些技巧很大程度依赖你对 SQL 的了解,SQL 对于程序员来讲也是一门很是重要的技能,没错 SQL 就是操做数据库的语言,据我了解大多数的公司在面试的时候都会考察程序员的 SQL 功底,扎实的 SQL 功底不只可让你写出高性能的查询语言外,对于数据分析,报表统计也是有很是大的帮助算法
大多数商业公司的核心资产其实就是数据库里面的数据,是很是宝贵的财富,程序和系统挂了,最多就是一段时间不可用,大可能是状况重启就能够恢复,可是是数据库不当心被误删了,若是是运维能力差的中小企业可能会面临倒闭的地步,从商业角度上来讲数据库大多数软件公司的核心sql
不少程序员从菜鸟成长到高手,接触的项目从学校的"某某管理系统"到刚加入公司内部系统,而后再到大型分布式系统,在大型系统中,大多数人程序员一般遇到的第一个问题一般不是线程不够用,不是CPU负载太高,不是内存不够快,一般都是数据库扛不住压力了,为何呢?数据库自己就基于磁盘的文件系统,每次读取数据都是经过 I/O 去访问磁盘,了解计算机原理的同窗应该都知道,在冯诺依曼计算机体系结构里磁盘 I/O 号称是最慢的 I/O (毫秒级),一般在你的系统只有几千上万的数据量时,全表扫描一般不会有很大的延迟感,可是当你的存量数据达到百万千万时,那么一次普通的查询就会把你的数据库服务器撑爆,作过应用的人都知道,数据库挂了,无论是什么分布式,微服务的牛逼架构都基本没啥用了,唠唠叨叨说到这里,相信你们应该已经知道数据库的重要性的,后面咱们再从数据库设计的角度来看下问题数据库
这里咱们简单作一个对比,良好的数据库设计能够为你带来什么 ?编程
糟糕的设计 ?服务器
糟糕的设计(图)微信
好比说对于一个简单的年龄字段,严谨来讲应该使用 tinyint(1字节)或者 smallint(2字节),可是你恰恰要用 int (4字节) 这就属于糟糕的字段选择,看到这里不少刚入门的同窗就可能就会反驳了,这么在乎空间利用是否是有点矫枉过正?包括存储已经很便宜了,还这么斤斤计较般的选择,反正最终实现的功能都是相同的,别人也看不出什么差异呀。对于这种观点其实我想反驳一下,这是典型的新手思惟,你只在看到在单个字段上的空间节省,可是没有考虑过数据也是在持续增加,糟糕的设计越到后期增加成本会越高(这里就相似于 Java 的经典面试题,集合类 ArrayList 和 LinkedList 在少许数据对比时看不出时间上的差距,可是随着计算数据量的上升,消耗数据的差距也会越拉越大),等到了千万级数据量的时候,可能你设计的表和别人设计的表是相同的内容,可是你的表无故的多出几百G的存储空间,若是你的应用仍是多数据中心的话,那么这种无故的空间浪费还会被拷贝几十倍到不一样的数据中心,并且只要你的应用还在线上运行,那么这种增加所带来的成本还会持续上升,这里也仅仅只是说对空间的浪费,下面在分析表结构存储上,还会具体说一下糟糕的设计对于性能会有多大的影响,这对企业来讲就是边际成本的递增,从技术和架构上来讲就会让你的系统不具有可扩展性
MySQL 的开放性架构设计兼容了不少不种类的存储引擎(要是你足够厉害的话,也能够本身写一套存储引擎),存储引擎的设计初衷就是应对不一样类型的数据仓库,工做中有见过无论什么表都直接用 Innodb(MySQL 5.0 的默认存储引擎,虽然大多数场景是不错的选择,但不是全部类型的表结构都适用)也见过根本不知道什么是存储引擎的同窗,若是这些同窗来设计数据库的话,那么你的系统就很容易踩到坑,出现不少你本身的预料不到的问题,合理的存储引擎的选择是应该结合实际业务场景,从目前最主流的 MySQL 来讲,最经常使用的存储引擎主要是 MyISAM, Innodb,固然还有不少其余的存储引擎,例如 NDB(集群存储引擎),Memory(基于内存的存储引擎),Archive(归档存储引擎),由于这些平时使用很少,并不主流,工做中也不多用获得,意义不大,因此就不展开来说,这里主要简单将下 MyISAM,Innodb 的区别,主要有如下特色:
MyISAM
Innodb
由于不了解数据库的基本原理,因此不少初级程序员在选择数据库字段类型的时候比较迷茫,主要仍是没有明确指导原则,工做中我见过在只有十几条数据的基础信息表中使用 long(8字节)做为 id 主键类型,还有就像上面说的状态类型字段只有 0,1 值的字段使用 int (4字节),还见过字符类型字段统一使用 varchar(255),数值类型字段统一使用 int,这种不基于数据库原理规则去随意选择字段的行为也只会出如今你 LocalHost 里的一些小项目或者玩具,基本上不了什么大台面
据我所知,主流的数据库大多都提供很是丰富的字段类型给开发者使用,老司机都是基于业务类型的判断从而选择合适的字段类型,最终收获的是性能(时间)和存储(空间)都很是低的高性能数据库,具体数据库有哪些字段类型,文章里面就很少数了,这方面的资料简直太多了,有兴趣的小伙伴能够本身去搜索,例如这里 MySQL Data Types,那么对于新手而言如何选择字段类型呢?
简单的基本原则以下:(后面会具体将缘由)
遵循基本规范能带来什么好处?
为何要把“选择尽量小的字段”做为基本原则?咱们能够先看下 innodb 的逻辑存储结构
innodb 逻辑存储结构(图)
innodb 的存储结构以下:
上图能够看到读取最小单元 Page,匹配的数据都是从 Page 里面取出,按照这个简单的逻辑来讲页中存储的行数据越多,数据库的性能就越高,怎么算出来的呢?按最小类型 2B 来计算 Row,那么 Page 的默认大小(16KB)是能够匹配到 7992 行记录,相反,若是你的 Row 行数据过大,假如一行 32 KB,那么数据库就须要 2 个连续的 Page 来保存你一行的数据,那么性能可想而知会有多低,先后性能差距差很少 1.6 万倍,这块也不深刻讲了,有兴趣的小伙伴推荐去阅读经典书籍,这里的内容也只是书里的冰山一角
索引是一种用空间换时间的优化手段,是数据库最重要的优化手段,也是最后的杀手锏,索引是否高效取决数据库设计是否良好,字段类型选择是否合理,索引是一把双刃剑,在提高检索速度的时候,也会减低插入,修改的性能(维护索引树的开销),在工做中这些年面试了不下几百人发现能把数据库索引原理讲明白的候选人很是的少,大多数状况下咱们说索引一般默认指的是 BTREE 索引,BTREE 结构是特地为磁盘 I/O 这种缓慢的读取存储设计的数据结构,是一棵多路多叉树,和二叉树相反,每层的元素很是多,可是树的高度很矮(一般不会超过三层),从而能够保证最多不超过三次磁盘 I/O 便可定位到匹配的元素,因此说 BTREE 是一种很是适合磁盘的数据结构,也是 MySQL 默认索引类型是 BREE 的缘由,若是能把这块吃透的话,那么去面试确定是很大的加分项,索引在数据库能够简单参考下图:
简单说了下索引的结构,那么新手程序员在使用数据库因此的时候能够遵循如下原则:
索引这块能够玩的还有不少,例如如何经过 SHOW INDEX 查看数据库为索引作出的评级(经过 Cardinality 统计),经过 Explain 查看 SQL 是否命中索引,rows 列能够看到 SQL 扫描的数据行数,Extra 列还能够查看索引匹配的类型,例如 Using index 表明彻底匹配索引(无需回到 Primary Key 表查询数据,也称回表,甚至直接使用索引的排序,无需排序)每每说明性能不错,Using temporary 表明查询有使用临时表,通常出现于排序,多表 join 的状况,查询效率不高,建议优化
人生总会遇到不少坑,与其本身去踩坑不如去总结别人踩过的坑,本身少走一些弯路也许能够更快的成功,这里是最后一章,不想把文章拉的太长,因此我在这里就直接抛出结论,不会再说明缘由,若是对数据库有兴趣推荐看到最后我推荐的书籍
避免使用触发器/存储过程
避免使用预留字段
反范式设计
尽可能避免使用 Null 字段
这篇文章写了三天(空闲时间),主要覆盖篇幅比较广,可是每一个主题都是在幼儿园的入门水平,主要是给不少新手程序员一个简单的参考,我我的认为看文章分享只是为了点燃兴趣,就像一道开胃菜,最终的造成本身的知识体系,熟悉知识完整的结构仍是推荐去阅读经典的书籍,这才是学习的正确姿式,数据库的书我读的不是不少,但仍是能够简单推荐两本我读过的而且感受很是不错的,而且本篇文章都是大量参考了书中的内容,很是值得推荐:
值得推荐的书就以上两本,若是以为看书不过瘾能够再推荐看看极客时间的 《MySQL 实战 45 讲》是由鼎鼎大名的数据库大神丁奇所写的专栏,若是用开药来比喻的话,看书就是内服,看专栏就等于外敷,总结就是,内服 + 外敷 疗效可能会好一些,最后打一波广告:若是要买极客时间专栏能够加我微信,我有推荐二维码而且返现红包,666666
更多技术咨询,请关注公众号,find me !