写在前面
上两篇聊了高可用和备份恢复,今天开始进入一个更硬核的话题——性能优化。以下仅仅是一些个人愚见,性能优化,个人推荐老虎刘,刘大师的课程、书籍以及优化方法论都是一流,有幸看过一些,学了刘大师的一点点皮毛,可关注刘大师的公众号和相关课程。
老虎刘谈性能优化
老虎刘,公众号:老虎刘谈SQL优化126-一次性能故障引申出来的8个SQL优化知识点
性能优化这事儿,说简单也简单,加索引、加内存、加机器,三板斧抡下去,大部分问题都能缓解。说难也难,因为错误的优化比不优化更危险——一个错误的索引可能让写入性能腰斩,一个错误的函数用法可能让索引失效,一个错误的 SQL 逻辑可能让整个系统雪上加霜。
这篇是性能优化系列的第一篇,我们先从最基础、最通用、也最容易被忽视的三件事讲起:
- 1.统计信息
—— 优化器的"眼睛" - 2.执行计划
—— SQL 的"体检报告" - 3.索引
—— 最快也最危险的武器
一、统计信息:优化器的"眼睛"
1.1 什么是统计信息?
先打个比方:你去餐厅点菜,服务员会告诉你"这道菜是辣的、那道菜份量大、这道甜点适合两个人吃"——这些信息帮你做决策。
数据库的优化器也一样。它在决定一条 SQL 怎么执行之前,需要知道:这张表有多少行?这个列有多少个不同的值?数据分布是均匀的还是倾斜的?索引的深度和选择性如何?
这些就是统计信息(Statistics)。
优化器根据统计信息来估算每种执行路径的成本,选择它认为"最优"的执行计划。如果统计信息不准确,优化器就会做出错误的判断——就像拿着过期地图导航,越努力越偏。
1.2 YashanDB vs Oracle:统计信息管理对比
核心差异:Oracle 的统计信息管理经过了二十多年的打磨,DBMS_STATS 包的功能极其丰富。YashanDB 在基础能力上完全对齐,但在高级场景(如增量统计信息收集、统计信息导出/导入等)还在持续完善。
1.3 统计信息为什么这么重要?
再举个真实的例子——
一张订单表有 1000 万行数据,status 列只有 3 个值:'PENDING'、'COMPLETED'、'CANCELLED',但数据分布极不均匀——99% 是 'COMPLETED','PENDING' 只有 1000 条。
业务执行:SELECT * FROM orders WHERE status = 'PENDING';
- 如果统计信息准确
:优化器知道 'PENDING' 只有 1000 行,会选择走索引扫描(Index Scan),毫秒级返回 - 如果统计信息过期
:优化器可能以为数据均匀分布,估算出 330 万行,选择全表扫描(Full Table Scan),几秒钟才返回
同样的 SQL,不同的统计信息,性能差距可以达到百倍甚至千倍。
1.4 收集统计信息的最佳实践
什么时候该收集?
表数据发生大量变更后(INSERT/UPDATE/DELETE 超过一定比例) 定期收集(如每天凌晨业务低峰期) 建表、重建索引之后 执行计划出现异常时
收集语句示例——Oracle:EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'TABLE_NAME');
;YashanDB:GATHER STATISTICS FOR TABLE schema.table_name;
💡 经验之谈: 很多生产环境的性能问题,根源就是统计信息不准。当你发现一条 SQL 突然变慢,第一件事不是加索引,而是先检查统计信息是否过期。
二、执行计划:SQL 的"体检报告"
2.1 执行计划是什么?
当一条 SQL 提交给数据库,优化器会生成一个"执行方案"——先扫描哪张表、用什么方式扫描、表之间怎么关联、数据怎么排序——这就是执行计划(Execution Plan)。
读执行计划,本质上就是读懂数据库"打算怎么做这件事"。
2.2 查看执行计划
YashanDB 查看执行计划示例:EXPLAIN PLAN FOR SELECT * FROM orders WHERE customer_id = 1001;
然后 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
2.3 执行计划常见"坑"
① 全表扫描(FULL TABLE SCAN)什么时候合理?
很多人看到全表扫描就慌,急着加索引。但全表扫描不一定是坏事:
表很小(几百行),全表扫描比索引扫描更快 查询需要返回表中大部分数据(>15%-20%),索引回表的成本反而更高 批量处理场景,顺序 I/O 比随机 I/O 更高效
什么时候不合理?大表(百万行以上)做精确查询却走了全表扫描;WHERE 条件有高选择性的列,但没建索引。
② 索引失效的常见原因
这是性能优化中最让人痛心的场景——明明建了索引,优化器就是不用。原因通常是:
③ 连接方式选择错误
YashanDB(和 Oracle)支持多种表连接方式:
优化器选错连接方式,通常是因为行数估算错误——又是统计信息的锅。
三、索引:最快也最危险的武器
3.1 索引的本质
一句话:索引是用空间换时间的艺术。
没有索引时,找一条数据就像在一本没有目录的字典里查字——只能从头翻到尾(全表扫描)。有了索引,就像有了拼音目录,几毫秒就能定位到目标页。
但索引不是免费的:每次 INSERT/UPDATE/DELETE,都要同步维护索引;索引占用额外的存储空间;过多的索引会增加优化器的选择难度。
3.2 YashanDB vs Oracle:索引能力对比
3.3 索引设计的"黄金法则"
法则一:高选择性列优先建索引
选择性 = 不同值数量 / 总行数
身份证号:选择性 ≈ 1(每行都不一样)→ 最适合建索引 性别:选择性 ≈ 0.0001(只有男/女)→ 几乎不适合单独建索引 订单状态:选择性低且数据倾斜 → 需要配合直方图
法则二:联合索引的字段顺序很重要
假设查询模式是 WHERE dept = ? AND hire_date > ?——好的设计是高选择性字段放前面(CREATE INDEX idx_dept_date ON employees (dept_id, hire_date)
),差的设计是低选择性字段放前面(CREATE INDEX idx_date_dept ON employees (hire_date, dept_id)
)。
原则:把过滤最多记录数的字段放在第一位。
法则三:覆盖索引避免回表
如果一个查询需要的所有列都包含在索引中,优化器可以只读索引、不读表——这叫覆盖索引(Covering Index),是性能优化的利器。
例如,查询只需要 customer_id 和 order_date,创建索引 CREATE INDEX idx_cover ON orders (customer_id, order_date)
,那么 SELECT customer_id, order_date FROM orders WHERE customer_id = 1001
这条 SQL 可以只读索引完成。
法则四:别建太多索引
每多一个索引,INSERT/UPDATE/DELETE 就多一份维护成本。经验法则:OLTP 表单表索引不超过 5-7 个;频繁更新的表索引越少越好;批量导入场景考虑先删索引导入再重建。
3.4 索引的反面教材
四、信息收集:优化前的"望闻问切"
在动手优化之前,最重要的事情是收集信息。中医讲"望闻问切",性能优化也一样——先诊断,后开药。
4.1 需要收集哪些信息?
4.2 YashanDB vs Oracle:性能信息收集工具
4.3 优化思路决策树
SQL 慢了? 按以下顺序排查——
第一步:检查统计信息是否过期。如果过期,收集统计信息后重新执行。
第二步:检查执行计划是否异常。全表扫描但表很大→考虑建索引;索引存在但未使用→检查失效原因(函数/隐式转换/数据分布);连接方式错误→检查行数估算,必要时用 Hint 引导;子查询效率低→改写为 JOIN。
第三步:检查 SQL 逻辑是否有问题。SELECT * 包含不必要的列→减少列;缺少分页→加 LIMIT/TOP;循环中调 SQL→改为批量操作;事务过大→拆分事务。
第四步:排除非 SQL 问题。锁等待→检查锁冲突;IO 瓶颈→检查磁盘和缓冲区;内存不足→调整缓冲区参数。
五、通用优化手法速查表
不管用 Oracle 还是 YashanDB,以下优化手法通用且高频:
六、尾声:人人都可以是全栈
写到这里,想起一件很有意思的事。
十年前,数据库调优是"高级 DBA"的专属领地——你需要懂存储引擎原理、会读 10046 trace、能背出各种隐含参数的作用。那个时候,"会调库"是一种稀缺能力,一种职业壁垒。
十年后的今天,AI 写 SQL 比你快,ChatGPT 分析执行计划比你准,Copilot 自动生成索引建议。甚至,一个刚毕业的前端工程师,借助 AI 工具,也能写出"八九不离十"的数据库查询。
壁垒在坍塌。
不是 DBA 不重要了,而是"只会调 SQL"的 DBA 不重要了。当 AI 能完成 80% 的执行计划分析,剩下的 20%——那些需要理解业务、理解数据分布、理解系统全局的能力——才是真正值钱的。最近又看到不少公司开始让“牛马”用AI和openclaw跑业务流程,跑通即刻下岗,用人跑AI,跑通流程后优化人。进入了一个奇怪的循环,各地都在大力推进一人公司{OPC公司},各种零元入住、各种OPC创业社区涌现,也是一个时代下的缩影,都在快马加鞭往前进。
这让我想到海子的那句诗。改一改,送给这个时代所有的技术人:
《面朝 AI,Token花开》
文:Acdante · 省略号先生
从明天起,
做一个全栈的人
写前端,写后端,连数据库,
从明天起,
关心 AI 和代码
一个人,搞定Docker,流程,业务,营销和流程
不断优化,不断跑通
用一个个Token,代替人工
用一个个Claw,实现流程
我有一台服务器,
面朝终端,春暖花开
从明天起,
和每一个 AI 通信
告诉它我的代码
那汹涌的Token闪电告诉我的
我将告诉每一个人
给每一条慢 SQL
取一个温暖的名字
陌生人,我也为你祝福
愿你有一个灿烂的前程
你在 AI 浪潮中获得幸福
愿你在技术更迭里找到归宿
我只愿面朝终端,春暖花开
技术在变,工具在变,但好奇心和学习力,是唯一不会被 AI 取代的东西。愿你我,都能在这新时代的新质生产力--词元-Token的冲击下,能够找到属于自己那片海。
作者:Acdante
系列:YashanDB 学习篇
上一篇:崖山数据库备份恢复与闪回:关键时刻能救命的"后悔药"
下一篇预告:YashanDB 性能优化(二)——内存管理与参数调优实战
如果觉得有收获,欢迎点赞、在看、转发三连。你的支持是我继续写下去的动力。





