马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?用户注册
×
Sybase ASE 性能调优:读懂查询计划与索引优化
一、具体的问题
很多刚接手 Sybase ASE 的 DBA,遇到"这条 SQL 在测试库秒回,到了生产库要跑三分钟"的工单时,往往第一反应是加机器、加内存,或者凭经验给某列"建个索引试试"。但 Sybase 优化器选不选你新建的索引、为什么偏偏走全表扫描、为什么同样一条语句在两个库表现天差地别,这些问题的答案都在查询计划(Query Plan)里。本文聚焦一个具体场景:如何借助 ASE 自带的工具把慢查询的瓶颈看清楚,并据此决定要不要调整索引,而不是盲加。
二、核心原理
1. 优化器靠统计信息做选择
ASE 的优化器是"基于代价的(CBO)"。它并不会真的去跑一遍,而是根据数据分布统计信息估算每种执行路径的代价,挑代价最小的。统计信息来自 update statistics:它采样各列的数据分布,生成密度(density)和直方图(histogram)。如果一张表长期不更新统计,优化器看到的数据量和真实情况差几个数量级,自然就会选错路径——这是生产库慢、测试库快的最常见根因。
2. 怎么看到真正的执行计划
ASE 不需要像 Oracle 那样单独调用 EXPLAIN PLAN 写进表,它直接在会话里用 set showplan on 把优化器选定的计划打印到结果集或日志。配合 set statistics io on 还能看到每张表的逻辑读/物理读次数,两者结合就能定位"哪一步读了最多的页"。注意:set showplan on 之后执行的语句并不会真的去取数据返回给你,它只输出计划文本,非常适合在排障会话里临时开启。
3. 索引在该不该建的判定
Sybase ASE 的索引分聚集(clustered)和非聚集(nonclustered)。聚集索引决定数据行的物理排序,一张表只能有一个;非聚集索引是独立结构,叶子存的是行定位符。优化器是否走索引,取决于"用索引查找的代价"和"顺序扫描的代价"谁更低。当查询的选择性很低(比如要返回表里 30% 以上的行),优化器宁可全表扫描也不走索引,因为随机 IO 反而更贵。所以建索引前,先看计划里到底是"index scan"还是"table scan",再决定动哪列。
4. 一个典型翻车现场
有一张每天插入百万级的流水表 t_trade_log,业务按 account_id 高频查询最近一笔记录。DBA 看 where account_id = ? 就给 account_id 加了非聚集索引,结果查询照样慢。打开 set showplan on 才发现:优化器走了全表扫描。原因是这张表从来没更新过统计信息,优化器以为 account_id 只有几个不同值(低选择性),判定扫描更划算。补做一次 update statistics 后,优化器立刻改成走索引,响应从三分钟降到几十毫秒。
三、实例参考(动手步骤)
下面用一套可照做的命令,演示"开计划 → 看瓶颈 → 更新统计 → 复核"的完整闭环。
- -- 1) 开启计划与 IO 统计(仅当前会话生效,不返回数据,只打印计划)
- set showplan on
- set statistics io on
- go
- -- 2) 跑那条慢 SQL,观察输出里是哪张表、哪种扫描
- select top 1 trade_time, amount
- from t_trade_log
- where account_id = 10086
- order by trade_time desc
- go
- -- 3) 查看该表当前的统计信息年龄(sysindexes 里 rowcnt/keys 是否严重失真)
- select name, rowcnt, keys1
- from sysindexes
- where id = object_id('t_trade_log')
- go
- -- 4) 针对高频过滤列更新统计(让优化器拿到真实分布)
- update statistics t_trade_log account_id
- go
- -- 5) 关掉计划,重新执行同一条 SQL,对比逻辑读是否大幅下降
- set showplan off
- set statistics io off
- go
复制代码
关键提醒:不要一上来就新建索引。update statistics 是零风险操作,而建错索引既占空间又拖慢写入。先确认计划里确实"该走索引却没走",再考虑建索引;建完用 set showplan on 复核优化器是否真的采纳。
四、实操检查清单
- 生产库慢、测试库快,第一嫌疑是否"update statistics 长期未做"?
- 排障时是否用 set showplan on + set statistics io on 真正看过执行计划,而非凭直觉加索引?
- 计划文本里慢查询的瓶颈步骤,是 table scan 还是 index scan?逻辑读最高的那张表是哪张?
- 高频过滤/连接列的选择性如何?返回比例超过两三成时,优化器走全表扫描其实是合理的。
- 新建索引前,是否先用 update statistics 排除"统计失真"这个零成本根因?
- 聚集索引是否建在"窄、唯一、递增"的列上(如自增主键),避免页分裂与写入放大?
- 建完索引后,是否用 set showplan on 复核优化器已采纳,并用逻辑读的前后对比验证收益?
- 统计信息更新是否有固定周期(如每周业务低峰),而非等出了慢查询工单才想起来?
|