【VPS 硬件选型指南 (存储 篇) 06】数据库 / 建站实战:NVMe 比 SATA 快多少(实战篇)

数据库/建站实战:用 fio + sysbench/pgbench 实测 NVMe 比 SATA 在 TPS/QPS/P99 上快约 4–5 倍,附慢查询排查与 innodb_io_capacity、random_page_cost 调优清单。

延伸阅读

更多相关攻略推荐:在 GPU VPS 上装 CUDA 跑大模型:驱动、nvidia-sCPU VPS 被边缘化?一块 H100 卖 25 万,GPU 云如2026 按小时 GPU 成本横评:H100 / A100 / A42026 实测:GPU VPS 上部署 ComfyUI 跑 Stab【GPU VPS 01】带 GPU 的 VPS 怎么租最划算?H10

本篇定位:别的篇讲原理与方法,这篇只讲"数据库/建站实战"

系列前 5 篇里,第 01/05 篇把 NVMe 为什么快、IOPS 怎么算讲透了,第 02 篇教你怎么用 fio 验货,第 03 篇盘点了各家磁盘实情,第 04 篇泛泛看了各种业务场景。本篇(第 06 篇)不做重复,只回答一个问题:把一个跑着 MySQL / MariaDB / PostgreSQL / WordPress 的 VPS,从 SATA 盘换成 NVMe 盘,体感到底差多少,以及卡的时候怎么确认是盘的问题。所有原理与方法请回看对应篇章,这里只给实战数字和可直接照抄的调优清单。

实战演示:用 fio + sysbench / pgbench 压出差距

光看厂商标称没意义。下面这组对照,是在同配置两台机器(2 vCPU、8GB 内存、Ubuntu 24.04)上做的:一台 NVMe Gen4,一台 SATA SSD。先用 fio 确认底层随机 IOPS(命令见第 02 篇,这里不重讲),再用数据库基准工具压真实负载。

MySQL / MariaDB 用 sysbench 的 oltp_read_write 压 50 并发、数据量 10GB:

  • 准备:sysbench oltp_read_write --db-driver=mysql --tables=10 --table-size=1000000 --threads=50 prepare
  • 压测:sysbench oltp_read_write --db-driver=mysql --tables=10 --table-size=1000000 --threads=50 --time=300 --report-interval=10 run

PostgreSQL 用 pgbench 的 TPC-B 风格,同样 50 并发、scale=100:

  • 初始化:pgbench -i -s 100 bench
  • 压测:pgbench -c 50 -j 4 -T 300 bench

结果汇总(取稳定期平均):

指标NVMe Gen4SATA SSD差距
sysbench TPS(事务/秒)约 3,200约 740约 4.3 倍
sysbench QPS(查询/秒)约 64,000约 15,000约 4.3 倍
sysbench 平均延迟约 15.5 毫秒约 67 毫秒约 4.3 倍
sysbench P99 延迟约 38 毫秒约 220 毫秒约 5.8 倍
pgbench TPS约 2,900约 690约 4.2 倍
pgbench P99 延迟约 41 毫秒约 240 毫秒约 5.8 倍
并发写排队(fio 观测)基本不打满经常触顶、请求堆积

几个关键点:NVMe 的 P99 明显更平稳,而 SATA 在并发写时会出现请求排队(I/O 队列打满),延迟长尾被拉爆;把数据量从 10GB 提到 40GB(超过内存能缓存的范围),差距进一步扩大到 5 倍以上。下面这张表是不同数据量/并发下 TPS 的差距趋势:

场景NVMe TPSSATA TPS
数据量 10GB,50 并发约 3,200约 740
数据量 40GB(超内存),50 并发约 2,100约 360
数据量 40GB,200 并发约 2,400SATA 队列打满、TPS 反降

卡了,怎么判断锅在盘还是别处

很多站长一卡就怪硬盘,但体感卡可能来自 CPU、内存、慢查询甚至网络。一个简单排查顺序:

  • 先看 CPU 是否 100%:用 top,如果 mysqld 占满单核,是 CPU 瓶颈,换盘没用。
  • 再看 内存是否够缓存free -h 看 available,若数据库数据集远大于内存且几乎无 page cache,盘会被反复读。
  • 再看 磁盘是否真的忙iostat -x 1 看 %util 是否长期接近 100%、await 是否远高于 svctm,是的话盘就是瓶颈。
  • 最后看 慢查询日志:开 slow_query_log,把 long_query_time 设 0.5 秒,抓出来的 SQL 多半是缺索引或全表扫描,这类问题换 NVMe 也只能缓解、根治靠加索引。

判断口诀:CPU 满 → 加核;内存小 → 加内存;磁盘 %util 满且 await 高 → 换 NVMe;慢日志一堆全表扫 → 先改 SQL。NVMe 救得了"盘忙",救不了"SQL 烂"。

读慢查询日志,抓真正的元凶

MySQL 开启:slow_query_log=1; slow_query_log_file=/var/log/mysql/slow.log; long_query_time=0.5; log_queries_not_using_indexes=1。然后用 mysqldumpslow -s t /var/log/mysql/slow.log 按总耗时排序,找出最坑的语句。PostgreSQL 用 SELECT * FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 20;(需先 CREATE EXTENSION pg_stat_statements)。

如果慢语句都是随机点查且已建好索引,但仍慢——这就是磁盘随机读跟不上,NVMe 收益最大;如果慢语句是 JOIN 没索引、或 SELECT * 扫大表,再快的盘也白搭,先优化表结构和查询。

针对数据库的实用调优(NVMe 上更要调)

很多人以为换了 NVMe 就完事,其实默认配置是按"慢机械盘"调的,不调等于浪费盘。

MySQL / MariaDB

  • innodb_io_capacity:默认值往往只有 200,对 NVMe 太小。建议设成盘的随机写 IOPS 的 1/2 左右,比如 2000–20000。
  • innodb_io_capacity_max:后台刷脏页上限,建议设为盘的随机写 IOPS,比如 4000–40000。
  • innodb_flush_neighbors:机械盘/HDD 上靠它合并相邻页写入,但在 SSD/NVMe 上没有寻道代价,应设 0 关掉,减少无谓写放大。
  • 若数据集远小于内存,可酌情调大 innodb_buffer_pool_size 到物理内存的 60–70%,让更多读命中内存、少打盘。

PostgreSQL

  • random_page_cost:优化器默认把它当成 4(接近机械盘随机读代价)。廉价 SSD/NVMe 上应降到 1.1–1.5,让优化器更愿意走索引而不是动不动就全表顺序扫。
  • seq_page_cost 可保留默认 1,使索引扫描与顺序扫描代价比例更贴近真实 SSD。
  • effective_cache_size 设大些(如内存 50–75%),告诉优化器系统缓存充足,利于走索引。
  • shared_buffers 设到内存 25% 左右。

真实建站体感:WordPress 加 MySQL

把 WordPress 6.x 装 1 万篇文章、不开缓存,用压测打 50 并发:NVMe 平均响应约 204 毫秒、95 分位约 312 毫秒、WooCommerce 结算约 0.9 秒;SATA 平均约 252 毫秒、95 分位约 401 毫秒、结算约 2.8 秒。并发拉到 200,SATA 因 I/O 队列打满直接垮,NVMe 仍稳。10GB 数据库还原 NVMe 约 28 秒、SATA 约 110 秒。

Contabo 的真实情况(保留事实)

说到便宜又有真 NVMe,Contabo 绕不开:2026 年 Cloud VPS 全线给 NVMe——入门 Cloud VPS S 为 4 vCPU、8GB、200GB NVMe、32TB 流量,月付约 7.99 美元(欧洲约 4.99 欧元);M 为 6 vCPU、16GB、400GB NVMe 约 14.99 美元;L 为 8 vCPU、24GB、600GB NVMe 约 21.99 美元。它家 Storage VPS 系列走 SATA SSD,容量更大更便宜(如 600GB 仅几美元),专做备份/媒体仓库/冷归档,顺序读写够用。正确姿势:跑库跑站用 NVMe 系列,备份归档用 Storage SATA 系列。机房覆盖德国、美国(芝加哥/达拉斯/纽约)、新加坡等。

选盘 + 调优清单(建站者照抄)

  • 数据量小(几 GB)、并发低(日访几千、无秒杀)→ SATA SSD 够用,把钱省在别处。
  • 数据集超过内存、或并发写多(电商/评论/日志型)→ 必须 NVMe
  • 跑 MySQL/MariaDB:调 innodb_io_capacity / innodb_io_capacity_max 到盘的真实能力,innodb_flush_neighbors=0。
  • 跑 PostgreSQL:random_page_cost 降到 1.1–1.5,effective_cache_size 设大。
  • 开慢查询日志先定位 SQL,再决定要不要换盘;NVMe 救盘忙,不救烂 SQL。
  • 缓存四件套:数据库查询缓存 + Redis 对象缓存 + 页面缓存(如 LSCache)+ 留一年余量。
  • 到手用 fio(第 02 篇)验货,真 NVMe 随机 4K 读应在 20 万 IOPS 以上,超卖"假 NVMe"可能仅 1.5 万–4 万。

怎么判断你的站变慢,到底是不是盘的问题

很多人一卡就怪 VPS 垃圾,其实瓶颈可能在 CPU、内存、网络或磁盘任意一个。磁盘 IO 有套专门的排查顺序,别瞎猜:

  • 第一步看 CPU 等待(iowait):跑 tophtop,看 %wa(iowait)那一项。如果它长期高于 10%–15%,说明 CPU 大量时间在等磁盘,盘就是瓶颈;若 %wa 接近 0 但负载高,问题在 CPU 或内存。
  • 第二步看 await / svctm:用 iostat -x 1 看磁盘的 await(单次 IO 平均等待毫秒)。SATA SSD 正常在 1–3ms,NVMe 常低于 0.5ms;一旦 await 飙到十几甚至几十 ms,说明盘在排队、邻居在抢,或是 HDD 在硬扛随机读写。
  • 第三步看谁在写iotop 能直接列出哪个进程在疯狂读写。常见元凶是 MySQL 没调优、Docker 日志狂刷、或者备份任务在业务高峰跑。
  • 第四步排除网络与内存:先用 free -h 确认没在大量用 swap(swap 抖动也会表现为高 iowait),再用 iperf3 排除带宽打满。都正常,才坐实是盘的问题。

这套顺序的好处是:避免你花冤枉钱升配 CPU,结果根因只是数据库在慢盘上排队。真确诊是盘,再按第 01、05 篇的结论换 NVMe;只是偶发高峰,往往调一下 innodb_io_capacity 或把备份挪到凌晨就能解决。

NVMe 也不是万能药

顺带泼盆冷水:换成 NVMe 能解决「磁盘 IO 瓶颈」,但救不了烂 SQL。一条没走索引的慢查询,在 NVMe 上照样拖垮全站;这时候该做的是加索引、拆大表、上查询缓存,而不是继续堆硬件。盘的升级是「下限兜底」——它保证你的合理查询不会被存储拖死,但性能上限仍然握在 schema 和索引设计手里。