那天我盯着那行跑了51秒的SQL,同事说,要不加个索引吧。
我没说话。
因为我清楚,就算索引建设得再精美,要是数据依旧在那块转速为7.2k转的机械硬盘上运转,那这个查询注定还是会卡顿。
我们总爱谈优化。
谈索引、谈执行计划、谈SQL改写。
谈了一整天,最后发现,慢的根本不是那条语句。
是磁盘。
什么是“命中”,什么是“没命”
大家都说缓存命中率要到99%。
99%听起来好安全。
可剩下的那1%,偏偏在你业务最高峰的时候砸过来。
IO延迟从0.1ms跳到70ms。
事务提交像在等一个迟到的人。
您前往查看V$SESSION_WAIT,其内容全部都是log file sync。
那一刻你忽然明白:
数据库从来不怕慢,它怕的是时快时慢。
你知道内存里住着谁吗
Buffer Cache。
SGA里那块最贵的地皮。
LRU算法仿若一位精明的房东,它常常会将最近使用过的房客留在客厅,而把那些不经常前来的房客驱赶至磁盘去睡觉。
但房东也有看走眼的时候。
进行一次全表扫描,能够将整栋楼里的租客全部替换一遍,热数据被驱赶出去,冷数据被邀请进来。
SELECT
(1 - (phy.value / (cons.value + db.value))) AS buffer_cache_hit_ratio
FROM
v$sysstat phy,
v$sysstat cons,
v$sysstat db
WHERE
phy.name = 'physical reads'
AND cons.name = 'consistent gets'
AND db.name = 'db block gets';
这叫缓存污染。
比你房东更不讲理的是Compaction。
在存算分离的架构当中,只读节点才刚刚将数据捂热乎,紧接着后台进行了一次合并,随后版本号就发生了改变。
缓存凉了。
查询又开始去对象存储拉数据,一秒变三秒。
真的有命中和没命中的世界
有人说SSD已经很快了,要缓存做什么。
可你测过吗?
NVMe是微秒级,机械盘是毫秒级。
差三个数量级。
而内存呢?
那是纳秒级。
是有没有的问题。
为什么90%的DBA在调缓存,10%在调命
因为调大小最简单。
将innodb_buffer_pool_size由4G调整为8G,敲下回车键,命中率提升了3个百分点。
你甚至可以炫耀:我今天优化了数据库。
ALTER DATABASE DATAFILE 'datafile_name' RESIZE 1024M;
可那些点没涨上去的3%呢?
藏在业务逻辑里。
藏在一条根本不走索引的Join里。
# 示例命令,使用rsync工具进行文件备份
rsync -avz /path/to/source /path/to/destination
藏在凌晨两点那个没人敢动的存储过程里。
关于IO抖动这件事
读这篇笔记的你,大概率被“尖刺”折磨过。
超融合平台上,IO曲线像心电图。
看起来平均延时还在能够忍受的范围之内,然而,当那根针被扎下去的时刻,前端订单竟然没法下单,产线指令居然发不出去。
你不是在优化性能。
graph TD;
A[检测到磁盘故障] --> B[隔离故障磁盘]
B --> C[更换新磁盘]
C --> D[系统自动开始数据重建]
D --> E[验证重建成功并重新加入存储池]
你是在消除不确定性。
当你调整shared_buffers的时候你在想什么
PostgreSQL建议设到总内存的25%。
Oracle说db_cache_size要多大你看着办。
AWS说交给自动管理吧。
自动管理当然省心。
# 在Linux环境下使用dd测试磁盘写入速度
dd if=/dev/zero of=testfile bs=64k count=16k conv=fdatasync
可省心的代价是什么?
是某个深夜,AMM把缓存调小了,把操作系统空闲内存调大了。
它以为那是空闲。
你的业务却以为那是灾难。
新硬件不一定治百病,但它能治穷病
我们这一代DBA,太习惯“凑合”了。
# 使用iostat命令查看磁盘IO统计信息
iostat -dx /dev/sda
习惯于在机械盘之上进行雕花操作,习惯于在虚拟化层面之中寻觅原因所在,习惯于去说服自身“瓶颈之处在于SQL,并非在于硬件”。
直到有人把全NVMe架构拍在你面前。
直到你看到那条跑了51秒的查询,0.1秒就出结果。
那一刻你忽然觉得:
过去那些年不是在调优,是在赎罪。
经验要不要写成程序
zCloud在做一件事:
将老DBA脑袋里的,“这里应当增加索引”,以及“那里不应该进行变动”,撰写成知识图谱。
AI说,这条SQL慢,改吧。
有的老DBA讲,速度是慢了些,然而这可是凌晨三点才生成的报表,而且一个月才运行一回,千万别去改动它,假设改动后出了问题,究竟谁来承担责任呢。
经验不是规则。
经验是:我知道什么时候该打破规则。
你调过redo log的位置吗
把控制文件放一块盘。
把redo log组放另一块盘。
把归档扔去第三块。
这叫物理分离。
十几年前的老手艺了。
现在的云数据库早就不让你碰盘符了。
你只能在“性能保障”那一栏,默默选个更高IOPS的套餐。
不是你不会调了。
BEGIN
DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT;
END;
/
是你没权限调了。
所以,缓冲区缓存到底为什么重要
因为它站在内存和磁盘中间。
替99%的查询挡住那1%的灾难。
ALTER SESSION SET sql_trace = true;
它不是最快的那条路。
但它是最稳的那堵墙。
写在最后
tkprof /path/to/tracefile.trc /path/to/outputfile.txt
那天我还是加了个索引。
因为51秒降到0.1秒那个案例,我用的是全NVMe。
可我手里这台机器,磁盘还是十年前的老伙计。
加完索引,查询从3秒变成1.8秒。
EXEC DBMS_STATS.GATHER_DATABASE_STATS;
同事说,哟,优化了40%呢。
我没告诉他,1.8秒对磁盘来说已经是极限了。
我同样没有将此事告知他,只要这儿的这片盘在今晚出现哪怕是一个扇区坏掉的情况,那这百分之四十便彻头彻尾是个笑话。
数据库优化做到最后,
不是和技术斗,
是和预算斗,
是和“够用就好”斗。
SELECT file_id, name, bytes, blocks, io_bytes_read, io_bytes_written
FROM v$datafile;
但我想了想,什么也没说。
只是默默把监控页面的缓存命中率,拖到了仪表盘正中央。

Comments NOTHING