|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?用户注册
×
一、具体的问题
一台跑了七八年的 ASE 生产库,开发报"越来越慢",但提不出具体慢在哪。DBA 上去看:CPU 用了 30%,内存还有富余,磁盘 IO 也不高,各项"资源指标"看着都健康。这种最麻烦——不是缺资源,是资源在低效地被消耗。这正是 sp_sysmon 的用武之地:它是 ASE 自带的性能采样报告器,一次 10 分钟的采样,能把 CPU 到底在忙什么、缓存为什么没命中、锁在等谁,全部分模块摊开给你看。
我处理过的典型症状有三类:一是批量作业时段 CPU 突然打满但业务没变;二是用户反映点查偶发卡顿,平峰却查不出来;三是加了内存命中率还是上不去。这三类问题的共同点是:靠看监控大盘的"总量指标"定位不了,必须看 sp_sysmon 这种"过程指标"。
二、核心原理
sp_sysmon 的原理不复杂:它在采样窗口内统计 ASE 内部各类事件计数(任务切换、缓存搜索、物理 IO、锁请求),窗口结束时输出差值和比率。所以第一个要点是采样窗口的选择:太短(1 分钟以内)数据抖动大,无法代表常态;生产上建议高峰期采 10 分钟。可以用 sp_sysmon "00:10:00" 直接跑,也可以 sp_sysmon begin_sample / sp_sysmon end_sample 手工掐表,后者适合配合复现某个具体操作。
第二个要点是看比率不看绝对值。报告里每个模块的数字是"次数/秒"这类绝对值,单看没有意义,要跟"占比"和模块间的相互印证结合。举例:数据缓存命中率 92% 看着还行,但同期 Kernel Utilization 里的 "cache search misses" 换算成每秒几千次 miss,且 Device I/O 显示读集中在某一个大表所在设备——那就说明有一张表在被反复做物理读,命中率是"平均值掩盖了热点"。
第三个要点是本篇最核心的反差点:命中率低,第一嫌疑不是内存不够,而是大表扫描在污染缓存。ASE 的缓存是 LRU 淘汰,一个没有合适索引的千万级全表扫描,会把几十万页灌进缓存,把热数据页全部挤出去。此时加内存只是延缓,建索引或把"冷数据扫描"隔离到独立缓存才是根治。同理,报告里的 APC(Average Pages per I/O,平均每次物理 IO 读的页数)低于 8,几乎可以断定存在大量随机小 IO——这是索引缺失的信号,不是缓存不够的信号。
第四个要点关于多引擎环境:ASE 每个引擎访问数据缓存都要抢缓存自旋锁(spinlock)。多 CPU engine 的机器上,default data cache 是单一全局锁,引擎越多争用越重——Kernel Utilization 里 "task context switches due to ... cache search" 持续偏高就是证据。解法是建命名缓存(named cache)把热表隔离出去,ASE 15.7 起还可以把缓存配置成多分区降低锁争用。
三、实例参考(动手步骤)
步骤 0:确认现状基线。 采样前先记录环境,避免解读报告时对不上号:
- select @@version
- go
- sp_configure "max online engines"
- go
- sp_configure "number of user connections"
- go
- sp_monitorconfig "number of open objects"
- go
复制代码
步骤 1:高峰期采集 10 分钟全模块报告。
输出较长,重点读五个模块。也可以只采单模块看细节,比如只看缓存:
- sp_sysmon "00:10:00", cache
- go
复制代码
步骤 2:逐模块解读,定位瓶颈。 按下面的顺序看,命中哪条走哪条治理:
| 模块 | 关键指标 | 健康参考 | 超标含义 | | Kernel Utilization | task context switches due to cache search | 趋近 0 | 缓存争用,多引擎机器尤其明显 | | Task Management | runnable tasks | 平峰应接近引擎数 | 排队严重,CPU 不足或有长事务占引擎 | | Data Cache Management | Cache Hit Ratio | > 95%(OLTP) | 低于此值先查大表扫描 | | Data Cache Management | APC | > 8 | 低于此值存在随机小 IO,查缺失索引 | | Lock Management | lock contention(等待/请求) | < 5% | 超过 10% 要定位热点表 |
步骤 3:本例的治理动作。 采样结果显示:命中率 87.3%,APC 4.2,cache search 引起的任务切换每秒 2400 次,Lock contention 14%。三步治理:
第一步,用 MDA 表找到大扫描的元凶(需已开启 MDA monitoring):
- select ObjectName, LogicalReads, PhysicalReads
- from master..monSysStatement
- order by PhysicalReads desc
- go
复制代码
确认是一张报表统计表被反复全表扫描。给它补了按查询日期的复合索引。
第二步,把剩余不可避免的扫描隔离到独立命名缓存,避免继续污染 default data cache:
- sp_cacheconfig "report_cache", "512M"
- go
- sp_poolconfig "report_cache", "16K", "256M"
- go
- sp_bindcache "report_cache", mydb, rpt_stat_daily
- go
复制代码
注意:sp_cacheconfig 修改缓存后需要重启 ASE 或按提示重配缓存才完全生效,命名缓存的 16K 池给大 IO 扫描用,能显著抬高该缓存的 APC。
第三步,重启后做复采样验证,确认指标收敛,再清理:
- sp_sysmon "00:10:00", cache
- go
- sp_unbindcache "mydb", "rpt_stat_daily"
- go
复制代码
(验证无误后此 unbind 不执行;仅当绑错表时用它回退,回退前先记录当前绑定关系。)
四、实操检查清单
- 采样窗口固定 10 分钟、选业务高峰时段,平峰采样结果不做容量结论。
- 报告解读顺序:Kernel → Cache → Lock → Device I/O,先进程行为再看资源。
- Cache Hit Ratio 低于 95% 时,先用 monSysStatement 找物理读大户,不要先加内存。
- APC 低于 8 的库,逐表核对高频查询的 WHERE 条件与索引前导列。
- 多引擎机器(max online engines > 2)每季度看一次 cache search 类任务切换,持续偏高考虑命名缓存隔离或缓存分区。
- lock contention 高于 10% 时,配合 monLocks 抓热点对象,评估锁粒度(datarows 锁)改造。
- 每次治理动作后必须复采样一次,用同一窗口长度做前后对比,拿数据说话。
几个容易踩的坑
一坑:拿平峰采样当性能结论。 有同事凌晨两点采了一份报告,命中率 99%,得出"缓存没问题",白天高峰照样卡。sp_sysmon 是过程快照,不在问题时段采等于没采。
二坑:只加内存不改扫描。 命中率 87% 就把缓存从 2G 扩到 8G,命中率升到 91% 就停手了——因为那几条无索引全表扫还在,每次扫描照样把热页挤出去。加内存是花钱买缓解,建索引才是根治。
三坑:sp_sysmon 采样本身就是开销。 采样期间 MDA 统计有额外 CPU 消耗,不要在业务最敏感的结算窗口长时间采样,也别把多轮采样连续排满一整天。
四坑:命名缓存绑错粒度。 sp_bindcache 支持绑到库、表、索引三级,误把整库绑进小缓存反而制造新的争用;绑定前想清楚"隔离的是哪类访问模式"。
治理前后对比
| 指标 | 治理前 | 治理后 | | Cache Hit Ratio | 87.3% | 98.6% | | APC | 4.2 | 11.8 | | cache search 任务切换 | 2400 次/秒 | 30 次/秒 | | Lock contention | 14% | 3% | | 批量作业时长 | 42 分钟 | 18 分钟 | | 客服工单(偶发卡顿) | 5~8 单/周 | 0 |
sp_sysmon 的价值不在报告多长,而在它把"慢"翻译成了模块化的证据链。养成高峰期定期采样、按模块排查、治理后复采验证的闭环习惯,多数"说不清的慢"都能落成具体的动作。 |
|