1.1 性能指标
数据库的性能通常由响应时间和吞吐量两个指标来衡量。响应越快,吞吐量越大,数据库性能越好。在某些情况下,响应时间和吞吐量不能一起改善。
1.2 调优级别
对Sybase可从四个方面进行数据库性能调优:
一) 操作系统级:提高网络性能、操作系统参数、硬件性能等。
二) SQL Server等级:调整访问方法,改进内存管理和锁管理。
三) 数据库设计级别:采用降范式设计,合理设计索引,分布存储数据等。
四) 应用程序级:高效SQL合理安排事务,应用游标,处理锁。
本文不讨论第一方面的内容,第二方面提到的概念只适用于Sybase但第三、第四方面讨论的问题也适用于数据库Sybase其他外部数据库。上述措施相互关联,具体解决性能问题,有时综合应用。
1.3 调优工具
在分析Sybase一些数据库系统本身提供的性能调统本身提供的一些性能调整工具,包括多个系统存储过程:
名称 |
简要介绍功能 |
sp_sysmon |
企业级系统性能报告工具 |
sp_lock |
检查锁的情况 |
sp_who |
查看线程的活动 |
sp_procqmode |
存储过程的查询处理模式 |
sp_configure |
配置SQL Server系统级参数 |
sp_estspace |
估计创建一个表需要的空间和时间 |
sp_spaceused |
估计表的总行数及表和索引占用的空间 |
sp_monitor |
监视CPU、I/O的统计活动情况 |
在利用isql等一些工具时,还可以设置查询会话中的几个选项,来显示SQL语句执行时的各种统计分析结果:
指令 |
On 的含义 |
set noexec on/off |
分析SQL语句后,还要执行 |
set statistics io on/off |
统计SQL执行所需I/O |
set statistics time on/off |
统计SQL语句执行耗时 |
set showplan on/off |
显示查询计划 |
1.4 sp_sysmon 的使用
企业级性能报告工具、系统存储过程sp_sysmon 的使用方法:
在isql 下,首先输入 sp_sysmon 'begin_sample' 启动一个报告采样
过一段时间后,再输入 sp_sysmon'end_sample' 结束上次报告采样
或者紧跟一参数 sp_sysmon 'end_sample',"dcache" 结束上次报告采样, 但只显示数据缓冲(Data CacheManagement)这一部分的情况。
能替换dcache的可选参数如下表所示:
参数 |
参数全称,内容范围解释 |
Dcache |
Data Cache Management,数据缓冲 |
Kernel |
Kernel Utilization,有关引擎、网络和I/O等情况 |
Wpm |
Worker Process Management |
Parallel |
Parallel Query Management |
Taskmgmt |
Task Management |
Appmgmt |
Application Management |
Esp |
ESP Management |
Housekeeper |
Housekeeper Task Activity |
Monaccess |
Monitor Access to Executing SQL |
Xactsum |
Transaction Profile |
Xactmgmt |
Transaction Management |
Indexmgmt |
Index Management,索引管理 |
Mdcache |
Metadata Cache Management |
Locks |
Lock Management,锁管理 |
Pcache |
Procedure Cache Management |
Memory |
Memory Management |
Recovery |
Recovery Management |
Diskio |
Disk I/O Management,磁盘I/O管理 |
Netio |
Network I/O Management |
1.5
用sp_sysmon可以得到数据库系统的性能基准报告,但要在比较稳定的状态下产生,方可作为参考和对照的依据。
1.6 理解存储方法
只有清楚数据库存储数据的底层细节,如数据页、索引页的物理结构,每一行的大小计算,不同类型列占用的宽度等等问题,才能对各种调优措施有个深入领会。关于这个问题,比较复杂和细致,请自行参阅有关书籍。
一般地,对于更改数据的操作,要尽量促进数据库进行直接更新( Direct Updates ),所以要遵守以下几条原则:
1)除非必要,避免使用允许null值的列和可变长度的列。
2)如果varchar 和varbinary 列填充得比较满,毫不犹豫转成 char 和binary 列。
对于建表时指定的页填充率(page fillfactor)参数,要权衡确定数值大小。一般:小值,适合于有许多随机插入的表,该表的数据经常被删除,又经常被增加;大值,适合于大多数的数据被增加到表末尾,如客票系统的售票存根和退票存根表。
2.1 管理共享内存
数据库性能优化的首要方面是最优管理内存。数据库占用的共享内存分成数据缓冲(data cache)、存储过程缓冲(Procedure cache)等几块。在isql 下使用 sp_configure 'cache' 可以看到存储过程缓冲所占百分比(procedure cache percent),整个数据缓冲大小(total datacache size) 等参数。
2.1.1 存储过程缓冲(Procedure cache)
存储过程缓冲保持以下对象的查询计划:
Procedures :存储过程
Triggers :触发器
Views :视图
Rules :规则
Defaults :缺省
Cursors :游标
存储过程不可重入,意即每个并发用户调用都会在内存中产生一个拷贝。
Procedure, triggers, and views 当它们被装载到procedure cache中时,被查询优化器优化,建立查询计划。如果存储过程在缓冲中,被调用时就不需要重新编译。如果procedure cache太小,存储过程就会经常被其他调入内存的存储过程冲洗掉,当再次被调用时,存储过程又被调入内存,再重新编译,用户请求因此不得不等待。最严重的情况,如果procedure cache不够,存储过程甚至都不能运行。所以在内存足够的情况下,procedurecache percent 参数尽可能大一些。
2.1.2 数据缓冲(Data Cache)
数据缓冲用来缓存数据页和索引页,是除去存储过程缓冲,系统其他占用的缓冲外的剩余内存空间。通过给服务器增加物理内存扩大数据缓冲,是最有效的方法。当然,如果不能加内存,就只能通过减少存储过程缓冲的比例等方法来扩大数据缓冲了。
通过 sp_configure "extent I/O buffers", 20(可调) 命令,在Data Cache中保留一些页专用于创建索引时使用,可以显著提高创建索引的性能。但要注意每开辟一个缓冲占用16K 字节的系统内存。
2.1.3 命名缓冲
通过如下的命令:
1> sp_helpcache
2> go
查看某客票数据库中命名缓冲,得到的结果如下:
Cache Name Config Size Run Size Overhead
------------------------------------- ---------- ----------
DS30_Tran_Log 20.00 Mb 20.00 Mb 2.05 Mb
Systemtable 20.00 Mb 20.00 Mb 2.05 Mb
default datacache 0.00 Mb 4462.86 Mb 464.97 Mb
left_base_center 16.00 Mb 16.00 Mb 1.57 Mb
price_cache 8.00 Mb 8.00 Mb 0.85 Mb
可以看出有4个命名缓冲,分别绑定客票系统的应用日志表、一些重要且常用的系统表、余票表、票价系列表,另外1个是缺省数据缓冲。这种配置还不是最合理,应该进一步把Systemtable这个命名缓冲细分成很多个,每一个单独存放一张系统表。
2.1.4 缓冲策略
缓冲策略是指把数据提前读入内存的机制,分预取策略(Prefetch Strategy,即大I/O策略)和取后马上丢弃策略(Fetch-and-Discard)、提示策略(Hints)等几种。
可以在三个级别上设置表数据的预取策略(Prefetch Strategy,即大I/O策略)于:对象级,会话级,查询级。如果三个级别上都有设置,它们发生作用的优先顺序是:对象级> 会话级 > 查询级。
对于如何在查询级利用指定的缓冲池,可以查看下面例子(使用4K缓冲池):
select au_fname,au_lname
from authers(prefetch 4)
where au_id in (A372020631, ..., A1887081515 )
go
DSS应用往往得益于大的I/O,应该放开large I/O strategy预取策略。
如果一个应用倾向于OLTP特征,用户能在会话级关掉Prefetch来提高性能。对于OLTP应用,关闭large I/O strategy预取策略。
对于所取到的页不会有重用的情况,放开fetch-and-discard策略。客票系统对存根数据进行统计的应用,如财收日结账,营销分析数据整理模块和综合查询等,都可以利用这一结论。
查看几个操作频繁且较大的表上的缓冲策略,用如下命令:
sp_cachestrategycenter,seat_area
sp_cachestrategycenter,sale_record0505
2.2 管理锁
2.2.1 页锁升级阀限
优化锁的重要考虑是设置页级锁升级升级成表级锁的阀限。要尽量避免页锁很快升级成表级锁。
在某客票数据库中,用sp_configure ‘lock’可以看到如下结果:
deadlock checking period 500 0 1000 1000
number of locks 5000 46875 200000 200000
page lock promotion HWM 200 0 10000 10000
page lock promotion LWM 200 0 200 200
page lock promotion PCT 100 0 90 90
可以看到页锁升级的阀限有三个:HWM(最高点) 为10000,LWM(最低点)为200,PCT为90。Sybase数据库内部根据PCT值按公式PCT*TAB_SZ/100得出计算阀限,如果计算阀限 < LWM, 锁升级发生在LWM值;如果计算阀限 < HWM,锁升级发生在HWM值。如果 LWM < 计算阀限 < HWM ,锁升级发生在PCT*TAB_SZ/100值。
锁升级阀限设置分对象级和服务器级两种。
针对对象级设置(数据库上的表或表上的索引),配置命令是:
sp_setpglockpromote{"database" | "table"}, objname, new_lwm,new_hwm, new_pct
针对服务器级设置,配置命令是:
sp_setpglockpromoteserver, NULL, new_lwm, new_hwm, new_pct。
如果要删除掉对象级上的页锁升级阀限,用:
sp_dropglockpromote{"database" | "table"}, objname
2.2.2 减少锁争夺的方法:
1)降范式设计数据库,创建冗余表。
2)把堆表(没有聚族索引的表)分区。
3)对于小表,使用fillfactor和max_rows_per_page来减少行密度,从而使各行数据分布到许多页(此方法适用于SQLServer 11版,对于11.9.2版以后的Sybase数据,有了行级锁,此方法必要性不大)。
2.3 管理临时库(tempdb)
管理临时库一个重要原则是要避免临时表跨多个设备,可以把tempdb从master设备中分离出来,放到一个单独的设备上去。这样可以减少存取系统表时对I/O资源的争夺。
用sp_dropsegment 存储过程从master设备中移除tempdb的default段和system段。
为了进一步提高tempdb的I/O速度,可以考虑把tempdb整个放在RAM 驱动器或固态存储设备上,存取速度是一般磁盘的1000倍。
一般情况下,tempdb会非常频繁地争夺和占用缺省数据缓冲,因为查询会话中有许多临时表要创建、计算和删除。所以推荐把tempdb绑定到它自己的命名缓冲,这样可以防止临时对象在内存中的活动冲洗掉缺省数据缓冲中的其他对象,利于在多个缓冲间展开I/O。在使用临时表的时候,还有一个原则:尽量缩小表规模和行的宽度,每一行只包括必要的列。例如在用select * into生成临时表时,如果只需要几个列的数值,就不要用这样的语句,而直接选取需要的列。
2.4 使用多引擎(MultipleNetwork Engines)
如果操作系统使用了多个CPU,那么用sp_configure 配置数据库的参数:在线引擎数(max online engines),可以扩展系统的网络I/O容量,分布网络I/O到各个引擎,从而提高性能,允许更多的用户连接。
在用户登录数据库时,总是先登录到引擎0,由引擎0在可用引擎队列中选择一个挂最少连接的引擎来传递socket描述符,从而重定向连接到那个引擎,由该引擎去处理跟此用户连接相关的所有网络活动。
对于多引擎SMP结构,SQL Server引入了自旋锁(spinlock)的一种数据结构,在多个引擎间共享。对于不同类型的任务,在哈希表上分配不同的自旋锁,有页锁自旋锁、表锁自旋锁和地址自旋锁。
自旋锁的配置:
sp_configure"page lock spinlock ratio", newval
sp_configure"table lock spinlock ratio", newval
sp_configure"address lock spinlock ratio", newval
增大数值,可以减少碰撞,提高并发操作度。但是每一个自旋锁结构要占用256字节的内存。
如果数据库发生1279错,可能原因:
1)不允许足够的锁,解决办法是用sp_configure 调大 number of locks 数值
2)在engine freelock 缓冲中没有足够的锁,解决办法是用sp_configure调大 max engine freelocks 数值。
如果数据库系统使用了4个引擎,那么每个引擎的自由锁缓冲中包含:each engine-specificfreelock cache 包含 5000 * .20 /4 = 250 个锁。
在平时,经常用sp_monitor和sp_sysmon监视CPU使用率,如果所有CPU的利用率高于85%,增加CPU,然后增大数据库的引擎数,可以改善性能。
2.5 设备使用的优化
把最常插入的表分区,放在多个设备上,这样可以创建多个页链,从而改善多个并发插入时的性能,因为每一个插入都要找到页链,页链有多个,就允许多个插入同时进行。这一点,尤其适用于客票系统的存根表和订票存根表(CG30_RRT),所带来的性能改善会非常明显。
物理I/O的代价远大于逻辑I/O,所以要尽量减少磁盘进行物理I/O的次数,尽量多进行内存中的逻辑I/O。使用statistics io工具和sp_sysmon,来观察磁盘I/O。可以配置使用大的I/O来减少物理I/O的次数,方法有三个:
1)用更多的磁盘;
2)表和索引分开到不同的磁盘;
3)增加一次I/O系统参数值的大小。
SQL Server总是为I/O请求建立一个磁盘检查的调度环,用sp_configure "I/Opolling process count"来提高数值,加长环,可以降低引擎的检查次数,提高吞吐量。但较小的值一般有助于减少响应时间。
对于可用的磁盘I/O控制块,要查看操作系统文档,用sp_configure "diski/o structures"配置,这个数值要尽可能高。
分离日志和数据,到不同的设备;给tempdb自己的设备;分离表和索引到不同的设备。这些方法都可以减少I/O。
4)数据库设备设置为异步写,在创建数据库设备时候带上 dsync = false 参数 。
2.6 对事务处理的调优
2.6.1 事务类型
事务处理无外乎三种:1,OLTP;2, DSS; 3, OLTP + DSS 的混合负载
OLTP(联机事务处理)的特点:
u 数据插入、修改和删除频繁。
u 经常操作的是单个记录。
u 当不适当设计时,倾向于碰撞和冲突。
DSS(决策支持系统)的特点:
u 数据修改不太频繁。
u 如果有插入和删除,是大批量的。
u 平时一般是只读操作。
u 表连接很常见。
u 有比较特别的查询。
OLTP + DSS 混合负载的特点权衡:
u 在性能方面要比较,是要吞吐量还是响应时间。
u 在锁方面要比较,是要并发性强呢还是要数据一致性强。
2.6.2 事务管理原则
一般的事务管理原则有:
1) 分解大的事务成多个小的事务。如客票数据的备份操作中,要删除过期数据,如果设计小事务做循环,便不会影响应用,完全可以做到任何时候备份和删除,不一定非得等服务器闲的时候做。
2) 避免在单个事务中更新或删除大量的数据行。比如客票系统的席位库数据清理,即使在服务器闲的时候做这种操作,也会锁定整个表,影响售票。
3) 尽量用可以接受的最低孤立级(isolation level),来提高并发度。如在余票查询等功能的应用中,使用这种孤立级,便可以最大程度地降低对售票的影响。
4) 提高事务吞吐量的措施包括:避免延迟更新;尽可能使用存储过程等等。
2.6.3 跟事务特征相关的数据库可调参数或特性
相对于OLTP应用,SQL Server有一些特性来满足要求。
1) 命名缓冲(Named cache)
对于命名缓冲,可以配置多个不同大小的内存池,来满足不同的应用需求。对于多个引擎的情况,命名缓冲还有一项重要的功能是降低自旋锁的内部争夺。
2) 日志I/O缓冲大小可配置
sp_logiosize ["default" | "size" |"all" ]
缺省值是4K,但如果4K内存池没有配置,SQLServer会使用2K大小的内存池
3) 堆表可分区,分布插入操作到各个设备
适用于频繁插入的表和有并发BCP倒入数据的表,如客票系统的售票存根和退票存根表。
4) 锁升级阀限可配置。
相对于DSS应用,SQL Server也有一些特性来满足要求
1) 应用大的 I/O 缓冲池
用sp_poolconfig来配置。
2) 绑定热表到命名缓冲
如 sysindexes, syslogs, 注意如果把 syslogs 放到单独的缓冲中,可以减少在缺省或其他命名缓冲上的自旋锁争夺。对于客票系统的train_dir, stop_time, 票价表, 取票存储过程相关的表都可以放在单独的命名缓冲上。
3) 取后丢弃缓冲策略 (Fetch-and-discard cachestrategy)