上一篇文中提到,IO瓶颈是导致SQL Server数据库性能下降的重要诱因。并提到可以使用性能监视器(Performance Monitor)来对磁盘性能进行持续分析。
其实,除了性能监视器之外,SQL Server数据库还专门提供了动态视图以帮助我们定位磁盘性能瓶颈。
我们都知道,当内存页不在内存缓冲池中的时候,数据库会创建一个IO闩锁等待,以便于更安全的将数据从磁盘加载到内存中。依照不同的数据访问请求类型,这个IO闩锁又可以分为两类:PAGEIOLATCH_EX、PAGEIOLATCH_SH。从字面意义上,“EX”即“Exclusive”,指“排他”;而“SH”即“Share”,指“共享”。
当数据库请求读取的数据所在的内存页不在缓冲区中时,数据库需要将数据从磁盘加载到缓冲区中。此时,数据库会对相关内存区域加PAGEIOLATCH_SH共享闩锁。
当数据库请求写入的数据所在的内存页不在缓冲区中时,数据库需要将数据从磁盘加载到缓冲区中。此时,数据库会对相关内存区域加PAGEIOLATCH_EX排他闩锁。
当然,由于数据库业务请求是不可确定的,因此数据库运行过程中,产生IO闩锁也是不可避免的。但如果闩锁存在的时间过长,就需要分析了。要判断是否存在IO瓶颈,并分析如何解决IO瓶颈。
通过查询动态视图sys.dm_os_wait_stats,可以了解IO闩锁的统计信息。当你发现数据库运行缓慢时,不妨阶段性的刷新这个动态视图,然后分析waiting_task_counts、wait_time_ms这两个字段的数据。
select * from sys.dm_os_wait_stats where wait_type like 'PAGEIOLATCH%' order by wait_type asc
下面的语句可以帮助你定位挂起的IO请求,这对定位IO瓶颈也很有帮助。
select database_id, file_id, io_stall, io_pending_ms_ticks, scheduler_address from sys.dm_io_virtual_file_stats(NULL, NULL) iovfs, sys.dm_io_pending_io_requests as iopior where iovfs.file_handle = iopior.io_handle
那么,如果我们发现了服务器存在IO瓶颈,应当如何优化呢?
首先,我们应当判断服务器连接的文件系统、磁盘类型。
对于Windows操作系统,常见的文件系统是NTFS。
对于服务器而言,磁盘类型按照接口类型,常见的为SAS、FC;按照磁盘驱动器类型,常见的包括机械硬盘和固态硬盘。
机械硬盘、SAS接口在NTFS文件系统下,在进行数据顺序读写时,性能更优。同时,当文件系统磁盘碎片较多时,磁盘读写性能会严重下降。此时,应当尽可能的定期进行磁盘碎片整理。
FC光纤连接、SSD或相关存储阵列,在进行数据随机读写时,性能更优。NTFS的磁盘碎片过多,也对该类磁盘的性能影响较小。
SQL Server数据库的相关文件,也应依照不同的磁盘接口、磁盘类型进行存放以实现最大性能。
如数据库日志文件,应当尽可能存放在服务器自身的SAS磁盘上,因为对于这些文件通常要进行顺序读写的操作。同时建议磁盘Raid模式为Raid1。
用户数据库文件建议保存在SAN存储网络的存储阵列上。以保障数据安全性,同时在读写性能上也能实现相对平衡。
临时数据库(TempDB),对数据的随机访问性要求较高,建议保存在SSD这类随机存储的磁盘上。
最后,建议将OLTP和OLAP系统环境分离,优化你的SQL语句,以避免不必要的IO操作。