MySQL学习笔记整理(一)

前言

       数据库是后台开发重中之重的一个环节,了解当前各种类型的数据库,并在了解各种数据库设计原理的基础上,深入学习相关优化策略,加之以实战经验,才是长久的发展之计。之后对先对关系型数据库–mysql为例进行深入学习笔记记录,毕竟开源,而且也是世界顶级的数据库,然后对非关系型数据库NoSql进行学习,以Redis为例,这些都已经接触过了,之后将做一个总结的笔记。

数据库的种类

  1. 对象数据库 应用领域:地理信息系统、科学与统计数据库、多媒体系统、XML文档仓库。
  2. 对象关系数据库 了解一下
  3. 关系数据库,例如mysql、oracle、sql server、db2等。我们以mysql为例深入了解关系数据库。
  4. 介于关系数据库与非关系数据库之间的MongoDB和完全的非关系数据库NoSql的Redis。Redis是我们了解的重点。

mysql数据库系统

       mysql由SQL接口、解析器、查询优化器、查询缓存(缓存和缓冲区)、存储引擎等几个子系统构成。

       图中还有几个部分解释如下:

connectors:与其他编程语言中的sql 语句进行交互,如php、java等;

Management Serveices & Utilities:系统管理和控制工具;

Connection Pool (连接池):管理缓冲用户连接,线程处理等需要缓存的需求。下面我们一个一个的来了解。

SQL接口

       SQL提供了从用户接收命令并把结果返回给用户的机制。关系数据库大都支持SQL标准,基本语句都类似,比如常规的CURD操作,sql server和mysql就差不多。mysql是一个多线程应用,它为每一个连接创建一个线程,每个线程执行都独立于其他线程。接收到SQL命令,解析各个部分存入一个类结构,查询结果通过有关数据写到网络通信协议上传输给客户端。

解析器

解析器使用Lex和YACC实现,它能够把一条SQL语句分解为命令字、选项和参数等一系列最基本的语法元素,并将这些存入一个Lex类的结构中,后面查询步骤都会使用这个。规则使用Lex和YACC编写,在使用Bison编译成一个词法解析器。

查询优化器

       查询优化策略有很多,也可以设计优化算法,高阶程序员也可以自己写查询优化器代替mysql默认的。sql server使用的查询优化策略是基于开销的,根据一系列等价规则为给定查询生成一系列查询评估计划,然后根据关于执行这个查询所需要的关系和操作性能指标数据中选出开销最小的。mysql是混合使用多种优化技术的数据库系统,围绕着选取-投影-联结策略而设计出来的,从整体上能保证生成好的,但不能保证生成最好的查询语句。属于启发式查询优化机制。

       具体的 选取-投影-联结 策略 :即先更具有关的限制条件进行选取(select操作)以减少要处理的元组个数,再进行投影以减少被选取元组里的属性字段的个数,最后根据联结条件生成最终的查询结果。

  1. 通过计算where子句里的表达式来横向排除多余的数据。
  2. 只保留在属性清单里面列出来的,以及在最后执行连接子句时还需要用到的属性字段,其他数据全部排除。
  3. 根据联结条件生成最终的查询结果。

       优化的第一步检查有关的表是否存在以及用户的访问权限。发现错误返回出错信息并把控制器交给线程管理器,也就是负责监听请求的listener,一旦找到了正确的表,就打开并应用适当的并发控制。
       所有的维护和初识化任务完成后,优化器将利用Lex结构对命令中where条件进行处理,其结果作为临时表返回后续步骤做一步处理。如果查询命令里面有UNION操作法,优化器将以循环方式执行完所有的select操作之后再进行下一步。
       优化器下一步时执行投影操作。这一步中间结果保存在临时表中且只保存指定列。最后检查Lex结构是否含有Join条件;如果有,调用join优化方法。

       优化内容:对条件表达式进行简化和求值,消除死分支或恒真恒假条件。总之,在执行联结操作之前,优化器会尽量减小查询命令里的条件。

查询执行

       查询的具体执行是由一组库方法实现,每种方法复制一种特点操作,例如CRUD。方法都有一个线程对象参数,可以让那些方法直接找到合线程访问相关的内部查询结构,加快执行速度。

查询缓存

       查询缓存,包括查询语句解析结果和查询结果本身。把频率最高的数据放在内存中能够快速的访问来加快。速度。mysql把数据封装成某个结构(不同对象缓存,用来封装的结构不同),再把数据保存为一个链表。缓存友表缓存(为了减少打开读取和关闭表,frm文件)、记录缓存(减少数据读写频率)、键缓存(缓存各索引的热度)、权限缓存(授权信息,存为先进后出的散列表)、主机名缓存(用栈)、其他类似联结缓存。缓存有自己的监控机制,利用LRU最近最少使用页面靠换策略。

存储引擎

       这个是重要的一环,也是mysql最佳功能之一。数据库使用者可以根据需求选择不同的存储引擎,存储引擎是关键的一部,也是数据库管理系统最底层的一个,直接与数据库文件进行交互,也就是对数据库进行IO操作。下面介绍mysql提供的一些存储引擎。

  1. MyISAM 是默认的存储引擎,它在ISAM上增加了一些新的缓存和索引机制。为了提高访问速度,这类表还普遍使用了数据压缩和索引优化技术。此外还准备了表级的锁定机制。所以适合检索读性能。
  2. InnoDB 几乎总是用在需要支持事务的应用程序。支持ACID,InnoDB所有索引采用B-树结构,放在叶子节点里。改进了并发控制,提供行级的锁定。所以对频繁更新,添加,删除等类型数据库是首选存储引擎。
  3. BDB提供页面即的锁。支持散列表、B-树。
  4. 内存存储引擎。HEAP表。
  5. 合并存储引擎。安装特定规则分成很多小表去存储一个大表,搜索的时候可以去搜索特定的小表而不是搜索体积庞大的大表。但是缺点是:只能用相同的myisam表,不允许替换操作,与普通表相比,使用索引访问效率要低。
  6. 档案。把大量数据保存为压缩格式,适合存放和检索那些不需要频繁更新的档案性或历史积累数据。比如系统日志。
  7. 联合存储引擎。适合用在分布式环境
  8. 群集/NDB 。 在一个高可用性和高性能的环境中使用多个mysql服务器提供数据库服务。
  9. 其他的包括:CSV、黑洞、定制的。

小结

       了解了一下数据库的类型,和mysql的组成,对RDBS的设计有了大致的了解,那么后面将对在此基础上对mysql优化进行一个深度的学习和总结,并找demo来实战。下面对SQL 语句执行过程进行说明:

       数据库通常不会被直接使用,而是由其他编程语言通过SQL语句调用mysql,由mysql处理并返回执行结果。那么Mysql接受到SQL语句后,又是如何处理的呢?

       首先程序的请求会通过mysql的connectors与其进行交互,请求到处后,会暂时存放在连接池(connection pool)中并由处理器(Management Serveices&Utilities)管理。当该请求从等待队列进入到处理队列,管理器会将该请求丢给SQL接口(SQL Interface)。SQL接口接收到请求后,它会将请求进行hash处理并与缓存中的结果进行对比,如果完全匹配则通过缓存直接返回处理结果;否则,需要完整的走一趟流程:

  1. 由SQL接口丢给后面的解释器(Parser),上面已经说到,解释器会判断SQL语句正确与否,若正确则将其转化为数据结构。

  2. 解释器处理完,便来到后面的优化器(Optimizer),它会产生多种执行计划,最终数据库会选择最优化的方案去执行,尽快返会结果。

  3. 确定最优执行计划后,SQL语句此时便可以交由存储引擎(Engine)处理,存储引擎将会到后端的存储设备中取得相应的数据,并原路返回给程序。

  4. 这里有几点需要注意:

       (1)如何缓存查询数据?

       存储引擎处理完数据,并将其返回给程序的同时,它还会将一份数据保留在缓存中,以便更快速的处理下一次相同的请求。具体情况是,mysql会将查询的语句、执行结果等进行hash,并保留在cache中,等待下次查询。

       (2)buffer与cache的区别?

       从上面的图可以看到,缓存那里实际上有buffer和cache两个,那它们之间是否有什么不同呢?简单的说就是,buffer是写缓存,cache是读缓存。

       (3)如何判断缓存中是否已缓存需要的数据

       这里可能有一个误区,觉得处理SQL语句的时候,为了判断是否已缓存查询结果,会将整个流程走一遍,取得执行结果后再与需要的进行对比,看看是否命中,并以此说,既然不管缓存中有没有缓存到查询内容,都要整个流程走一遍,那么缓存的优势又在哪里??

       实际上,并非如此,在第一次查询后,mysql便将查询语句以及查询结果进行hash处理并保留在缓存中,SQL查询到达之后,对其进行同样的hash处理后,将两个hash值进行对照,如果一样,则命中,从缓存中返回查询结果;否则,需要整个流程走一遍。

链接参考:mysql原理

说明

       文中出现的图片,文字描述有些来自互联网,但是出处无法考究,如果侵犯您的相关权益,请联系我,核实后我会马上加上转载说明。谢谢!!!