热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

小觑数据库(SqlServer)查询语句执行过程-mysql教程

近年来,越来越多的NoSql产品不断的以技术革命的者的身份跳出来:你看哥是多么的快,你们关型型数据库真是战五渣阿。是的,高性能的场景下NoSql真的很出彩。而我们关系型数据库只能在墙角哭泣是的,没错,他们真的好快。但是他们为啥哪么快?用了雷政富光环

近年来,越来越多的NoSql产品不断的以技术革命的者的身份跳出来:你看哥是多么的快,你们关型型数据库真是战五渣阿。是的,高性能的场景下NoSql真的很出彩。而我们关系型数据库只能在墙角哭泣"是的,没错,他们真的好快。 但是他们为啥哪么快?用了 雷政富光环

近年来,越来越多的NoSql产品不断的以技术革命的者的身份跳出来:“你看哥是多么的快,你们关型型数据库真是战五渣阿”。是的,高性能的场景下NoSql真的很出彩。而我们关系型数据库只能在墙角哭泣"是的,没错,他们真的好快”。

但是他们为啥哪么快?用了雷政富光环了吗?我们从了解数据库引挚执行过程来了解一些基础知识,看看我们关系型数据库到底慢在哪?我只粗懂一些SqlServer,只能从SqlServer讲起。但是SQLServer是一个非常复杂的软件。我们将通过一个查询的执行过程让你对SQlServer的核心引挚和运行过程做一个简单的了解。

由于Select语句和Update语句基本一样,但是Update涉及到修改语句,所以我们直接从一条Sql语句开讲。update 码农表 set 女友=1 where 女友=0当我们码农写下这样一条Sql,小手轻按F5。 一个女朋友就产生了 一条语句在客户端被以TDS(Tabular Data Stream)协议形式中发给SqlServer服务端的网络接口(SQL Server Network Interface)。 什么是TDS协议这不重要。 因为TDS是一个专属协议,最早由Sysbase公司设计用于与数据库服务交互。你无须过多关心。SNI是一个 协议层用于在服务端和客户端建立网络连接,自SqlServer2005以后才有。它由一系列同时使用API组成。
这些都不是我们要讲的重点,我们接着往下说。SNI收到TDS包解包后发现,哟,小子又提交Sql语句了。就将这个包标识为一个Sql命令,将此Sql命令发给命令解析器 command parser。 command Parser首先检查语法错误,如果发现语法错误,将错误通过协议层发回给客户端。如果语法验证通过,则会生成查询树。

查询树生成以后,SqlServer要进行一个非常消耗CPU的工作,就是根据查询树生成查询计划。SqlServer 并不是简单的将一个查询树翻译成查询计划,而是经过不断的比较和权衡。一条SqlServer可能有很多种查询计划.比如Select Name from table where a=1 如果这个表上没有任何索引,那么可能生成的查询计划就是表扫描。如果在A列上有索引,那么可能应用A列上的索引,也可能不用。总之,SqlServer比较各种方案找到一个开销最小的执行计划。而这个找到最小执行计划的过程,也是比较消耗CPU资源的。

为了更加有效的利用资源,SqlServer会对查询计划行缓存。将之前执行过的查询计划保存在内存中反复使用。 这里有个很有意思的性能优化点。因为内存对SqlServer来说也是非常重要的。如果缓存了大量的查询计划也会影响到SqlServer性能。那么不缓存费CPU,缓存费内存。我们该怎么办?我们应该更加高效的利用查询计划缓存。举个例子。刚才我们执行的语句update 码农表 set 女友=1 where 女友=0 然后又执行 update 码农表 set 女友=0 where 女友=1 对于SqlServer来说,它会把这当成二条完全不同的语句来处理。

这里有一个定义:以单独的SQL语句的形式执行的查询就是即席查询(Adhoc)。我们经常在程序里拼的sql,就是这种既席查询。

如果你的系统中有大量的既席查询,会产生大量查询计划缓存。所以推荐大家在程序中写Sql时,尽量的使用参数化。update 码农表 set 女友=1 where 女友=@女友数 既高效又防Sql注入,何乐而不为呢?

到上面为止,完成这些工作的组件都属于Sqlserver的关系引挚部分。关系查询可以说是SqlServer中最复杂的组件。用于确定查询的最佳执行方案。而市面上大多NoSql数据库没有关系引挚这部分。语句处理比较简单。 这就节约了一部分开销。

而数据的访问和管理则由存储引擎负责。事实上我也不算说存储引挚部分的细节。我们只谈谈关系型数据库和NoSql不太一样的部分。SqlServer和大多数NoSql数据库一样,都是非常依赖内存的。内存比磁盘快。这是人所共知的。 SqlServer也有将数据缓存中内存中的机制。每次查询请求数据时 SqlServer先在在内存中查询有没有对应的页。 这里的页是指一个段连续的8KB内存。这段内存是将数据库文件中的页(每个页8KB)直接映射到内存中的。如果发现有查询需要的页将直接将对应的页的内容打包成结果返回。如果没有,SqlServer则先去磁盘中找到对应的页将它载入内存。再将内存中的页返回。而查询结束,内存中的页也不在回收。将一直保存到内存中。直到SqlServer发现操作系统可用内存不足,才会将一些不常使用的内存页还给操作系统(多聪明)。而且SqlServer会预先分配一些空白的内存页。这样等到用时就不用现分配了。 知道了上面原理,你就能明白 为什么Page Life Expectancy (PLE) 性能记数器的数值越大越好了。Page Life Expectancy (PLE) 越大表示一个页面在内存在呆的时间越长。也就是说你的内存压力越小。

可是,如果要是更新时SqlServer怎么办?我们知道关系型数据库对持久性的要求比好多NoSql产品都有节操多了。那数据库是如何保证持久性(喂不要想太多)和尽量提高性能的呢?
SqlServer使用了一种叫预写式日志的技术。简单来说就是你不是叫我干活吗?活还没干呢,我先把我要干的活写下来。然后等我有空时再干活。这么做有什么好处呢?
首先,我们知道磁盘的随机写入性能是很低的,相反,顺序写入性能要比随机写入高很多。如果每次用户更新数据时,都写入到数据库文件,那么很有可能产生一个随机读写。这样可能会影响性能。而SqlServer采用的是先写入日志。然后只更新内存中的对应的数据页。而日志一般都是顺序写入文件尾部的。这样一次随机的读写就被转换成一次顺序写加一次内存修改。性能自然有效提升。 而一般的NoSql数据库默认情况下并不保证写入的持久性。有的是定时刷到硬盘,但是并没有预写式日志,有的是先让你返回,成功不成功你再来问一次。

那SqlServer又是如何保证内存中的数据被回写到硬盘呢?SqlServer和上面提到有些NoSqL有点类型。SqlServer有一个叫 Lazy Writer 线程,用于周期的检测 空闲缓存页的值,如果这个值较低,他将扫描正个数据缓存将较长时间没有没使用的页面过期。如果他发现一个很长时间没有被使用的脏页,他也会将被更的页面但还没有回写到硬盘的页–也叫脏页写入到磁盘,并将他在内存中标记为空闲页。
那如果SqlServer突然断电,而内存中的脏页并没有来得及写入到硬盘肿么办?SqlServer使用一种叫检查点的机制。
检查点进程确保任何和已提交事务相关的脏页能被写入到磁盘,也将未提交事务的脏页写入磁盘以确保效率。和Lazy Writer 不同,检点查并不将页面移出缓存。他只是将脏页刷入磁盘,然后页面头标识这个页面为 Clean Page。 默认情况下,在一个忙碌的服务器上,SQL Server 大约每一分钟发起一个检查点并记录在事务日志里。如果SqlServer 实现或数据库重新启动,那么恢复进程通过读取事务日志就知道那些工作是在检查点之前做的。检查点之前做的工作,他不用理会。注意:CheckPoint的触发条件,是在CheckPoint期间生成日志的大小。因此,大家见过内存中有很多脏页,却不引发CheckPoint的情况。
当SQL Server非正常原因关闭时,也就是在没有走CheckPoint(会在下面提到)时关闭了数据库,此时数据库中数据本身可能存在不一致的问题。因此在数据库再次启动的时候,会去扫描日志,找出那些未提交却写入持久化存储的数据,或已提交却未写入持久化存储的数据,来进行Undo和Redo来保证事务的一致性。SqlServer 会尝试保证数据库恢复时间小于1分钟,但是,至少需要有10M数据写入日志,sQLServer才会触发CheckPorint

到这,你也就明白了为什么数据库会慢于NoSql产品了。当然这也只是我所理解的一方面。可能还有很多地方NoSql有优化的地方。如果简化掉关系引挚,去掉预写式日志,数据库性能会不会也有质的飞跃呢?可这一切又值得吗?
另外,如果你的数据文件和日志如果在一个磁盘上,那个可能这个预入式日志优势会大打折扣。原因你一定想的到。
其实我只是借这NoSQL火抱一下大腿。这篇贴子并没有大多NoSql的内容。我对NoSql也不太了解。但是现在你不会NoSql你都当了意思和人家打招呼了。NoSql在一些对事务性要求不太高的地方大有用武之地。我打算看完硬盘里的波多老师作品就去学习Nosql
了。

推荐阅读
  • Pikachu平台SQL注入漏洞详解
    本文详细介绍了SQL注入漏洞的基本原理、攻击流程、不同类型注入点的识别与利用方法,以及基于union联合查询、报错信息、布尔盲注、时间盲注等多种技术手段的信息获取方式。同时,探讨了如何通过SQL注入获取操作系统权限,以及HTTP Header注入和宽字节注入等高级技巧。最后,提供了使用SQLMap自动化工具进行漏洞测试的方法和常见的SQL注入防御措施。 ... [详细]
  • 本文详细介绍如何在Spring Boot项目中集成和使用JPA,涵盖JPA的基本概念、Spring Data JPA的功能以及具体的操作步骤,帮助开发者快速掌握这一强大的持久化技术。 ... [详细]
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 软件测试行业深度解析:迈向高薪的必经之路
    本文深入探讨了软件测试行业的发展现状及未来趋势,旨在帮助有志于在该领域取得高薪的技术人员明确职业方向和发展路径。 ... [详细]
  • Python与MySQL交互指南:从基础到进阶
    本文深入探讨了Python与MySQL数据库的集成方法,包括数据库连接、数据表创建、索引管理、数据操作以及如何防止SQL注入等关键内容。适合初学者及希望提升数据库操作技能的开发者。 ... [详细]
  • mybatis相关面试题 ... [详细]
  • 本文详细介绍了如何解决在使用本地SQlyog客户端尝试连接阿里云上的MariaDB数据库时遇到的2003错误,即无法连接到MySQL服务器的问题。 ... [详细]
  • 本文探讨了如何利用 Application 对象在 PHP 应用程序中共享数据,特别是在多用户环境中保持数据的一致性和安全性。文章还介绍了 Application 对象的基本结构、方法和事件,并提供了实际应用示例。 ... [详细]
  • 解决MySQL Administrator 登录失败问题
    本文提供了解决在使用MySQL Administrator时遇到的登录错误的方法,包括启动变量和服务部分禁用的问题。同时,文章还介绍了通过安全配置模式来解决问题的具体步骤。 ... [详细]
  • 远程访问用户 Kindle通过电子书实现控制
    介绍自2007年以来,亚马逊已售出数千万台Kindle,令人印象深刻。但这也意味着数以千万计的人可能会因为这些Kindle中的软件漏洞而被黑客入侵。他 ... [详细]
  • 设计模式系列-原型模式
    一、上篇回顾上篇创建者模式中,我们主要讲述了创建者的几类实现方案,和创建者模式的应用的场景和特点,创建者模式适合创建复杂的对象,并且这些对象的每个组成部分的详细创建步骤可以是动态的变化的,但 ... [详细]
  • 本文介绍了如何在Laravel框架中使用Select方法进行数据库查询,特别是当需要根据传入的分类ID查询相关产品时的正确做法和注意事项。 ... [详细]
  • 2023年1月28日网络安全热点
    涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ... [详细]
  • 美团安全响应中心推出全新配送业务测试活动,带来双重福利,邀您共同参与! ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
author-avatar
手机用户2502895961
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有