SQLpassion Performance Tuning Training Plan
个人学习翻译,如有谬误,请不吝指出,感谢.
Week 1: SQL Server如何执行一个查询
在我们进入SQL Server性能调优的繁杂细节之前, 我想先列举一下SQL Server如何执行一个查询(query)的结构,
这部分内容非常重要, 因为了解这些概念, 对我们以后的性能调优课程会理解的更加深刻.
下面的图为我们展示了SQL Server执行查询过程中所包含的几个主要组成部分:
SQL Server内部可以分离成两个部分:
Relational Engine 和
Storage Engine. 其中在
relational engine 中最大的组件是
Query Optimizer .
它唯一的任务就是把我们传给SQL Server的查询产生一个物理执行计划(
physical execution plan)
读取数据
首先,我们提交给SQL Server的查询经由
Protocol Layer(协议层)传给
Command Parser(命令解析器), 后者检查语法是否合法, 引用的表、列等对象是否正确.
Command Parser最后产生的结果就是所谓的
Query Tree, 它描述了我们的查询结构, 为后续的Query Optimizer所用,从而产生执行计划.
编译好的执行计划随后交由
Query Executor执行, 但在执行之前,执行计划会先被
Plan Cache缓存起来, 以作复用(Plan Cache是一个非常有用同时也非常危险的概念,后面在week10我们会谈到这些).
在执行计划被缓存后, Query Executor开始和Storage Engine交互,执行每一个操作.
当我们的查询需要访问数据(大部分都是select)时,
Access Methods会先向
Buffer Manager询问是否有我们想要读取的指定数据页(下一节我们来讲数据页: Pages, 现在你只要知道pages就是一个8kb的存储区间),
Buffer Manager管理着
Buffer Pool, 后者保存着很多数据页, 它是SQL Server中主要的内存消耗者, 我们可以在配置中设定它的大小Size.
如果被请求的页已经存储在Buffer Pool中, 则可以立即被返回. 这称之为逻辑读(Logical Read). 如果被请求的页不存在于Buffer Pool中, 则Buffer Manager会异步发起一个IO操作, 将被请求页从存储系统中读进Buffer Pool中,这称之为物理读(Physical Read).
整个查询必须等待物理读的异步操作完成才可以,我们在week22,再讨论等待的一些细节.
一旦所有的请求页都读进了Buffer Pool,就会返回给Access Methods,然后执行计划完成后,处理完的数据就会经由protocal layer返回给应用程序.整个查询到此完成.
修改数据
当我们运行一些insert,update,delete等会修改数据的命令时, Storage Engine会额外用到
Transaction Manager. 它的作用是写一条日志记录到Transaction log中, 以描述我们的操作产生了哪些变化. 这条日志记录会迅速的硬化, 并提交. 这意味着我们的SQL Server实例会尽可能快的处理事务日志. 页首先在内存中被改写,然后再写入到磁盘上, 这中间的过程我们称之为
Check Point, 它每时每刻都在运行, 不断的向Buffer Manager请求脏页(dirty pages). 脏页即已在内存中产生了变化,但未及时写入到磁盘中的页. 一旦脏页写入到磁盘,就会被标记为干净页.
总结
如你所见, 当我们执行一个简单的查询时, SQL Server内部发生了许多的事情,不同的角色承担了不同的功能, 在调优过程中, 我们不得不应对每个角色都有可能产生的一系列性能问题.