目录
(一)SQL SERVER查询生命周期简介
(二)基于上图的详解
1. 协议层
(1)共享内存
(2)TCP/IP
(3)命名管道
(4)VIA
2. 表格数据流端点
3. 命令解析器
4. 查询优化器
5. 查询执行器
6. 数据访问方法
7. 缓冲管理器
8. 数据缓存
(1)查询当前每一个数据库的缓存大小
(2)查询每个库中的脏页数量
9. 事务管理器
(三)小结
下图展示的是一个用户从发出请求到得到SQL SERVER响应的流程,即查询生命周期。
以下将详细介绍下上图中的每个部件大致的作用,内容经过整理和总结。
在用户发起对数据库请求后,该请求通过网络接口(SQL SERVER NETWORK INTERFACE,SNI)传到协议层中。SNI是客户端和服务器之间的连接,对于目前已发布的SQL SERVER版本,有以下4种网络协议。
它是默认开启的网络协议,也是最快最简单的协议,但是有一定的局限,只能在SQL SERVER所在的本机使用。这也是为什么经常能够在本机连接到SQL SERVER,但是外部极其连不上的原因之一,如果外部访问所需的协议没有开启,外部访问就不能连接SQL SERVER。而且,由于本机使用了共享内存协议,所以不需要做任何配置就可以连上。这个协议仅用于检查连接问题。
这是互联网上最常用的协议,可让外部访问通过IP地址和端口号(默认1433)来访问SQL。 SERVER。
它与TCP/IP类似,不过仅限于局域网访问。该协议默认使用445端口,所以如果使用这种协议,需要确保这个端口的可用性。
这几乎是个没有用的协议,并且SQL SERVER出现的很多问题都是由于开启了这个服务导致的,可能在后续版本中将会移除(实际上在SQL SERVER 2012已经找不到VIA的影子了),所以不建议用户使用。
小结:
不管使用哪种协议,一旦连接接通。SNI会创建一个安全的TDS端点,用于接收和发送请求。
表格数据流端点(Tabular Data Stream Endpoints)起源于Sybase,现在是微软专属的网络协议。一个网络协议一旦连接成功,就会创建一个对应的TDS端点,用于在客户端与服务器之间互传信息。
对于这一步,性能问题可能会出现在把请求的内容转换成SQL SERVER能处理的格式的过程中,如果数据量大,转换开销就高,不管是从外部传入SQL SERVER还是从SQL SERVER输出到外部,都是如此。
在TDS把请求转换成SQL SERVER内部可识别的格式后,首先会传到命令解释器(Command Parser)处,这个组件会检查传入的T-SQL语法是否符合规定,如果语法不符合要求,就会报错并通过TDS把错误信息传回客户端,最后结束过程。如果语法符合要求,就会生成查询树传入查询优化器中。
命令解释器同时也会检查是否已经存在缓存了的执行计划,如果存在,就重用;如果不存在,就让查询优化器生成执行计划。
该组件是SQL SERVER的核心部分。优化器的作用是对特定的请求进行一系列的优化,使其尽可能高效地对数据进行操作。最终选择最低开销的候选计划生成预估执行计划,并传入查询执行器执行查询。
正如其名,查询执行器是执行查询的组件,但是实际上并不真正执行,而是通过OLE DB协议访问并使用一系列的指令操作存储引擎进行查询的执行操作。存储引擎才是实际的查询执行者。
数据访问方法是提供数据和索引的存储/查询/修改的代码集合。它包含了所有操作数据的代码,但是并不由它自己去实际操作数据,而是提交请求到缓冲管理器。
缓冲(Buffer)管理器是管理Buffer Pool的组件。Buffer Pool是SQL SERVER内存的主要部分,它管理内存中的数据,并把适当的数据作为输出传输给(数据访问方法)。如果所需数据不在内存中,缓冲管理器需要从磁盘读取对应的数据页到内存的数据缓存,然后把所需的数据返回给数据访问方法。这个过程中可能会出现一种等待状态PageIOLatch。
数据缓存(Data Cache)是Buffer Pool中的最大部分,也可以说是SQL SERVER中占用内存最多的部分。它用于存放从磁盘加载到内存中的数据,以便后续操作使用。
select count(*) * 8 / 1024 as 'Cached Size (MB)',
CASE database_id
WHEN 32767 THEN 'ResourceDb'
ELSE DB_NAME(database_id)
END AS 'Database'
FROM sys.dm_os_buffer_descriptors
GROUP BY DB_NAME(database_id),database_id
ORDER BY 'Cached Size (MB)' DESC
缓存中的数据并不是一直存放的,当数据很久没被使用,或者SQL SERVER感觉到有内存压力时,就会释放一部分数据缓存。在该过程中会调用一个叫Lazy Writer的进程,这个进程会把脏页(从磁盘加载到内存后有改动过的数据页)写入磁盘,并释放这部分的空间。如果对实例中每个数据库的脏页数量有兴趣,可以用如下SQL去查:
SELECT DB_NAME(database_id) AS 'Database',
COUNT(page_id) AS 'Dirty Pages(KB)'
FROM sys.dm_os_buffer_descriptors
WHERE is_modified = 1
GROUP BY DB_NAME(database_id)
ORDER BY COUNT(page_id) DESC
TIPS:
如果想知道SQL SERVER保留数据缓存中的数据时间,可以查看性能监视器中的MSSQL$<实例>:Buffer Manager\Page Life Expectancy计数器(PLE)的值。这个值也是判断是否有内存压力的指标之一,微软的建议值是不小于300秒。但是需要说明的是,微软的建议值多存在一定的误导性,比如这里就是一个:300秒是基于4GB内存的32位系统得出来的。对于拥有32GB内存的64位操作系统来说,国外的专家给出的建议是PLE的值不少于2400秒。
事务管理器主要包含两部分:锁管理器和日志管理器。
1)锁管理器通过使用锁机制来保证数据的并发性和隔离性
2)日志管理器通过预写入日志机制,保证事务的ACID特性
TIPS:
当需要修改数据时,数据访问方法会先到事务管理器中通过对事务日志进行操作,把请求传到Buffer管理器中完成,然后返回给数据访问方法并通过事务管理器写入日志文件中。
SQL SERVER是一个复杂的系统,完全了解它的结构几乎不可能,但是每一步出现问题都将对稳定使用和性能带来比较大的影响。