设为首页 收藏本站
查看: 685|回复: 0

[经验分享] 从程序员的角度深入理解MySQL

[复制链接]
发表于 2018-9-28 07:55:37 | 显示全部楼层 |阅读模式
前言
  作为一名工作了4年的程序猿,今天我将站在程序员的角度以MySQL为例探索数据库的奥秘!
数据库基本原理
DSC0000.png

  第一,数据库的组成:存储 + 实例
  不必多说,数据当然需要存储;存储了还不够,显然需要提供程序对存储的操作进行封装,对外提供增删改查的API,即实例。
  一个存储,可以对应多个实例,这将提高这个存储的负载能力以及高可用;多个存储可以分布在不同的机房、地域,将实现容灾。
  第二,按Block or Page读取数据
  用大腿想也知道,数据库不可能按行读取数据(Why?   ^_^)。实质上,数据库,如Oracle/MySQL,都是基于固定大小(比如16K)的物理块(Block or Page,我这里就不区分统一称为Block)来实现调度和管理的。要知道Block是数据库的概念,如何对应到文件系统呢?显然需要指出“这个Block的地址在哪里”,当查找到地址后,读取固定大小的数据就相当于完成了Block的读取了。
  数据库很聪明的,它不会仅仅只读取需要读取的Block,它还会替我们把附近的Block块都读取加载至内存。实际上,这是为了减少IO次数,提高命中率。事实上,一个Block块的附近Block也是热点数据,这种处理方式很有必要!
  第三,磁盘IO是数据库的性能瓶颈
  毫无疑问,数据在磁盘上,少不了磁盘IO。什么磁头旋转,定位磁道,寻址的过程,就不说了,我们是程序员,也管不了这些。但是这个过程确实是非常耗时的,和内存读取不是一个数量级,所以后来出现了很多方式来减少IO,提升数据库性能。
  比如,增加内存,让数据库把数据更多的加载至内存。内存虽好,但也不能滥用,为什么这么说呢?假设数据库中有100G数据,如果都加载至内存,也就说数据库要管理100G磁盘数据+100G内存数据,你说累不累?(数据库要处理磁盘和内存的映射关系,数据的同步,还要对内存数据进行清理,如果涉及数据库事务,又是一系列复杂操作......)不过这里需要指出的是,为了加快内存查找速度,数据库一般对内存进行HASH存放。
  比如,利用索引,索引相比内存,是一个性价比非常高的东西,后文详细介绍MySQL的索引原理。
  比如,利用性能更好的磁盘...(和咱们就没关系呢)
  第四,提出一些问题思考下:
  为什么我们说利用delete删除一个表的数据较trancate一个表要慢?
  【一个按行查找删除,多费劲;一个基于Block的体系结构删除】
  为什么我们说要小表驱动大表?
  【小表驱动大表会快?什么鬼?M*N和N*M不是一样的么?有鬼的地方,就有索引!】
探索MySQL索引背后的原理
  对于绝大数的应用系统,读写比例在10:1,甚至100:1,而且insert/update很难出现性能问题,遇到最多的,最棘手的就是select了,select优化是重中之重,显然少不了索引!
  说起MySQL的索引,我们会冒出很多这些东西:BTree索引/B+Tree索引/Hash索引/聚集索引/非聚集索引...这么多,晕头!
索引到底是什么,想解决什么问题?
  老生常谈了,官网说MySQL索引是一种数据结构,索引的目的就是为了提高查询效率。
  说白了,不使用索引的话,磁盘IO次数比较多!要想减少磁盘IO次数,怎么办?
  我们想通过不断缩小想要获取的数据的范围来筛选出最终想要的结果,把每次查找数据的磁盘IO次数控制在一个很小的数量级,最好是常数数量级。
  为了应对上述问题,B+Tree索引出来了!
Hello,B+Tree
  在MySQL中,不同存储引擎对索引的实现方式是不同的,这里将重点分析MyISAM和Innodb。
DSC0001.png

  我们知道对于MyISAM引擎而言,数据文件和索引文件是分离的。从图中也可以看出,通过索引查找到后,就得到了数据的物理地址,然后根据地址定位数据文件中的记录即可。这种方式也叫"非聚集索引"。
  而对于Innodb引擎而言,数据文件本身是索引文件!通俗点说,叶子节点上,MyISAM存储的是记录的物理地址,而Innodb上存储的是数据内容,这种方式即"聚集索引"。
  另外一点需要注意的是,对于Innodb而言,主键索引中叶子节点存储的是数据内容,而普通索引的叶子节点中存储的是主键值!也就是说,对于Innodb的普通索引字段查找,先通过普通索引的B+Tree查找到主键后,然后通过主键索引的B+Tree进行查找。从这里你可以看出,对于Innodb而言,主键的建立非常重要!
  而对于MyISAM而言,主键索引和普通索引仅仅的区别在于主键只需要查找到一条记录即可停止,而普通索引允许重复,找到一条记录后需要继续查找,在结构上没有区别,如上图所示。
深入B+Tree
  提几个问题:
  为什么B+Tree把真实的数据放到叶子节点,而不是内层节点?
  为什么我们说索引字段要尽可能短,最好是单调递增的?
  为什么复合索引存在最左匹配原则?
  范围查询(>, 26 and sex = 'man',实际上只利用到了复合索引的name列。
想利用索引,就得“干净”
  什么叫“干净”?就是不要让索引参与计算!比如在索引上应用函数,很可能导致索引失效。为什么呢?
  其实不用想,B+Tree上存储的是数据,要比较的话,需要把所有的数据都应用上函数,显然成本太大。
想建立索引,看看区分度
索引虽然物美价廉,但是也别乱来。count(distinct col) / count(*)可以算一下col的区分度,显然对于主键而言,就是1。区分度太低的话,可以考虑下,是否还有必要建立索引呢?
Hash索引
  这里并不是要深入分析Hash索引,而是要说明一下Hash的思想真是无处不在!
  在MySQL的Memory存储引擎中,存在hash函数,给一个key,通过hash函数进行计算得到地址,所以通常情况下,hash索引查找,会非常快,O(1)的速度。但是也存在hash冲突,和HashMap一样,通过单链表的形式解决。
  思考下,hash索引是否支持范围查询呢?
  显然是不支持的,它只能给一个KEY去查找。就如同HashMap一样,查找key包含"zhangfengzhe"的,会很快么?
SQL优化神器:explain
  SQL优化的场景很多,网上的技巧也很多,完全记不住!
  要想彻底解决这个问题,我想只有把索引背后的数据结构和原理做适当的理解,遇到书写SQL或者SQL慢查询的时候,我们有基础去分析,再利用好explain工具去验证,就应该问题不大呢。
  explain查询的结果,可以告诉你哪些索引正在被使用,表是如何被扫描的等等。这里我将演示个Demo。
  数据表student:
DSC0002.png

DSC0003.png

DSC0004.png

  OK,到这里,准备结束了,查询容易,优化不易,且写且珍惜!


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-603013-1-1.html 上篇帖子: MySQL in不走索引 下篇帖子: 使用zabbix监控mysql主从状态
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表