关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

2026 服务器租用攻略:QuestDB 时序写入与内存映射选型,SSD 随机写与内存该怎么配

发布时间:2026-10-13

2026 服务器租用攻略:QuestDB 时序写入与内存映射选型,SSD 随机写与内存该怎么配

这篇不是数据库选型横评,不打算把 ClickHouse、TimescaleDB、InfluxDB 拉出来打分排名。它只回答一件事:你已经决定在自有或租用的服务器上自建 QuestDB,跑行情落地、业务监控、IoT 采集、设备遥测这类时序写入,那么这台机器的内存、SSD、CPU 到底该怎么配,钱该优先砸在哪一项上。

我们把账拆成四本——mmap 页缓存账、写入吞吐账、SSD 随机写与寿命账、CPU 与并发账——每本都给可以代入自己业务数字的算式,而不是甩一句"推荐 32 核 128G"。下面这五条是全文结论,后面每一条都会拆开算一遍:

1. 先算热时间窗,再倒推内存,顺序不能反。QuestDB 是列存 + mmap,查询落在内存里还是落在磁盘上,差别是几秒和几十秒的差别。

2. 看进程 RSS 一定会误判。mmap 出来的页归操作系统页缓存管,不进 QuestDB 进程的 RSS 统计。top 里看到 3 GB,实际可能吃掉 180 GB。

3. 写入瓶颈通常不在网络,在 commit 策略和乱序写入。commit 阈值配小了写放大直接翻倍;乱序数据触发的分区重写是 SSD 随机写的头号来源。

4. SSD 挑的是掉电保护,不是标称顺序带宽。WAL 要 fsync 真落盘才算数,没有 PLP 的消费级盘在断电瞬间会丢已确认的写入。

5. 核数按"并发查询 + 写入线程 + WAL apply 线程"之和再留三成余量。向量化执行下单条 SQL 未必吃满核,抢核的是并发数。

mmap 账:热时间窗的数据量就是你要留给页缓存的内存量

为什么同一条 SQL 有时候飞快、有时候卡死

QuestDB 的存储结构是:每张表按时间分区(DAY / MONTH / YEAR / HOUR / NONE),每个分区内部按列拆成独立文件(常见后缀 .d),写入是往列文件末尾追加,读取通过 mmap 把文件页映射进进程地址空间。

mmap 的关键在于:命中的页在页缓存里就是内存访问(纳秒级),没命中就触发缺页中断,从 SSD 把 4K 或更大的块读上来(NVMe 随机读常见 80–120 µs,SATA SSD 是毫秒级)。差着三到四个数量级。

于是一个很现实的现象:同一条"查最近 7 天每台设备的平均温度"的聚合 SQL,在热窗完全驻留内存时 2 秒返回;在热窗只有一半驻留时,可能要 20 秒甚至更久。SQL 没变、数据没变,变的只是缓存命中率。这也是为什么 QuestDB 的容量规划里,内存这一项的本质不是"给进程用的内存",而是"给页缓存当热数据容器的内存"。

一个可以直接代入的算式

热窗数据量 = 每秒行数 × 86400 × 有效行宽(字节)× 热窗天数。

有效行宽怎么取?QuestDB 做了列存 + symbol 字典化 + 时间戳编码之后,单行占用的常见区间是 8–20 字节:全是 double 型测点、字段少的表能压到 8–12 字节;带字符串字段、字段数超过 15 个的表会撑到 20 字节以上。取 12 字节做一个基准口径,后面表格都按这个算。

举个例子:2 万行/秒 × 86400 × 12 字节 ≈ 20.7 GB/天(预估口径)。如果业务上"最近 7 天"是高频查询区间,热窗数据量就是 145 GB。

那这台机器配多少内存?不是 145 GB,而是 145 × 1.5 ≈ 220 GB,再给操作系统和 QuestDB 进程本身的堆、symbol 表、查询中间结构留 16–24 GB,落地就是 256 GB 这一档。为什么乘 1.5?三个原因:页缓存里除了热窗列数据,还混着分区元数据文件、WAL 段文件、查询排序溢出的临时文件;操作系统的 LRU 不会精确地只保留你"想要"的那些页,总有一部分被冷数据占着;一旦有并发的大范围扫描查询,会把热窗页挤出去一部分,需要缓冲。

为什么盯着进程 RSS 一定会误判

mmap 映射的文件页属于内核管理的 page cache,是可回收内存,不计入 QuestDB 这个 Java 进程的 RSS(只有实际被访问过的映射页会以 file-backed 形式部分计入,而且随时能被回收)。所以生产环境里经常看到这种反差:top 里 QuestDB 进程 RES 只有 3–6 GB,而 free -h 里 buff/cache 有 180 GB。

判断"热窗到底进没进缓存",我一般这么干:

一是 free -h 看 available 而不是 free 那一列,available 才是还能给页缓存腾出来的量;二是用 pcstat / mincore 这类工具直接看列文件的缓存驻留比例,比看进程内存准得多;三是最实用的一招——同一条聚合 SQL 连跑两次,第一次和第二次耗时差 5 倍以上,就说明第一次基本都在落盘读,第二次才是真实内存速度。这个差值就是你该加多少内存的直接依据。

内存不够,加 swap 能救吗

不能,而且会更糟。mmap 的页一旦被换出到 swap,一次查询就退化成随机磁盘 IO,NVMe 上也是 80 µs 起步,比内存访问慢三个数量级;如果 swap 落在机械盘上,那就是毫秒级,整台机器会进入"活着但谁都访问不了"的状态。

QuestDB 这类 mmap 数据库上线第一件事就是关掉 swap,或者把 vm.swappiness 设成 1。宁可让 OOM 直接把进程干掉再拉起,也不要它慢慢地在 swap 里爬。在监控告警、行情这类场景里,慢 100 倍就等于全站失效,还不如干脆挂掉触发切换。

顺带提一个容易被忽视的内核参数:vm.max_map_count。分区数 × 列数会直接换算成 mmap 区域数量,按月分区、几百张表、每张几十列的库,映射数很容易顶到默认的 65530。上生产前先把它提到 262144 以上(经验值),否则会在业务量上来之后报"too many open files"或直接 mmap 失败。

写入账:WAL 顺序追加、ILP over TCP 的吞吐天花板与 commit 批次怎么配

ILP over TCP 的吞吐上限卡在哪

QuestDB 的 ILP(InfluxDB Line Protocol)默认监听 TCP 9009,写入端用 Telegraf、官方客户端或自研 SDK 建长连接推数据。官方公开的 ILP 基准在百万行/秒量级(8–16 核 + 本地 NVMe 的裸金属环境);我们在租用机器上压出来的实测数字通常是 20–80 万行/秒(非官方承诺值,取决于每行字段数、是否开 dedup、乱序比例)。

真正卡住吞吐的,一般不是网络带宽,是下面三件事:

第一是每行字段数。10 个字段的行和 3 个字段的行,吞吐能差 2–3 倍。列存要按列分离写入,列越多,一次 commit 涉及的文件句柄和映射页就越多,元数据开销摊不薄。设计表结构时能合并的字段就合并,别把 30 个测点铺成 30 列。

第二是 commit 策略。QuestDB 有两个关键参数:maxUncommittedRows(未提交行数阈值)和 maxCommitLag(最长提交间隔,微秒级,具体默认值以你所用 QuestDB 版本的官方配置文档为准)。这两个配小了,commit 就过于频繁,每次都要做元数据落盘 + fsync,写放大直接翻倍。我一般的调法是把 maxUncommittedRows 提到10 万–50 万行量级、maxCommitLag 给到几百毫秒量级,让一次 commit 攒够数据量再落盘。反过来也别无限调大——调太大,一次 commit 要写的文件变大,突发写延迟会变长,故障恢复时要回放的 WAL 也更多。

第三是分区粒度。按 DAY 分区,一天的写入落在同一分区的一组列文件里;按 MONTH 分区,一个月的数据共用一个分区文件。MONTH 的文件更少、句柄更省,但一次 commit 触及的文件更大,乱序重写代价也更大。这笔取舍的判断线很清晰:日增 50 GB 以上选 DAY,日增 5 GB 以下选 MONTH,中间的按你的查询习惯(是不是经常整月扫描)定。

WAL 顺序追加的好处,以及它的两笔代价

WAL 启用之后,写入先以纯顺序追加的方式落到 WAL 段文件——这是 SSD 最擅长的 IO 模式,然后由 apply 工作线程批量刷进列文件。好处是把潜在的随机写变成了顺序写,并且让乱序数据在 apply 之前有机会先排序。

代价有两笔,都要提前算进容量:

数据要写两遍。WAL 一份、列文件一份,日均写入量按 2 倍估算。这也是后面算 SSD 寿命时最重要的一项。

WAL 段必须 fsync 才算落盘。这是数据安全底线,任何"为了性能把 fsync 关掉或放宽"的做法,都是拿数据换吞吐。见过有人为了把写入从 40 万行/秒拉到 60 万行/秒去动 fsync 策略,然后一次机房掉电丢了十几分钟数据——这笔账怎么算都是亏的。

乱序写入(O3)是写放大的头号来源

传感器离线补传、网络抖动导致的延迟上报、跨时区采集端时间戳不统一——只要数据不是严格按时间戳递增到达,QuestDB 就要把新数据插进已有分区的中间位置,做法是重写该分区从插入点往后的那一段。

具体量级感受一下:日分区、每天 50 GB、凌晨集中补传 2% 的昨天数据,一次就可能重写几百 MB 到几个 GB。这类重写是"随机写 + 大块写"的混合负载,既吃 IOPS 也吃带宽,还吃 SSD 的 DWPD 额度。

能规避就规避。采集端做本地缓冲、按时间排序后再回放,比让数据库在写入侧兜底便宜得多。如果补传不可避免,至少把补传窗口错开到业务低峰,别和实时写入叠加打爆 commit。

SSD 随机写账:commit rewrite、DROP PARTITION、dedup 随机读对 4K IOPS 与寿命的压力

4K 随机写 IOPS 怎么看才不被参数表忽悠

厂商参数表上那个漂亮的随机写 IOPS,基本都是 QD32、4K、裸盘、无文件系统、稳态之前测出来的。QuestDB 的真实负载长这样:WAL 顺序追加(大块,几 MB 级)+ commit 时的列文件追加或重写(几百 KB 到几 MB)+ dedup 的随机读(4K–16K)+ 后台的排序临时写。

所以选盘要看三个数,而不是一个:4K 随机写的稳态 IOPS(不是峰值)、SLC cache 用尽之后的持续写入带宽(不是标称顺序写)、DWPD 或 TBW。

消费级 TLC 盘标 2–3 GB/s 顺序写,那是 SLC cache 里的数字;cache 打穿之后常见掉到 300–600 MB/s。QuestDB 一次 commit 可能就是几百 MB 的突发写入,正好是最容易把 SLC cache 打穿的模式——白天写入平稳时一切正常,晚高峰一批 commit 打下来延迟直接翻几倍,这种间歇性抖动最难排查。

把 DWPD 反算一遍,寿命够不够一目了然

算一遍就很清楚。假设日均写入 300 GB:WAL 双写 ×2 = 600 GB,乱序重写再按 1.3 倍算 ≈ 780 GB/天。

  • 一块 3.84 TB、DWPD=1 的 enterprise SSD,5 年保修期允许的总写入约 3.84 TB × 1 × 1825 ≈ 7 PB,日均额度 3.84 TB。780 GB 只占 0.2 DWPD,寿命绰绰有余,五年后可以放心换。
  • 换成一块 1 TB、600 TBW 的消费级盘,日均 780 GB,769 天就把总写入额度跑完,两年出头。

所以规模一旦上到日均几百 GB,消费级盘不是"能不能跑"的问题,是"能跑多久"的问题。而且 TBW 耗尽之后的失效模式通常不是立刻坏,而是写入延迟飙升、坏块增加,正好赶上业务最忙的时候。

掉电保护(PLP)这条比寿命更要命

WAL 的全部前提是:fsync 返回成功,数据就已经在非易失介质上了。消费级 SSD 多数没有掉电保护电容,DRAM 缓存里的写入在断电瞬间可能丢失,而操作系统已经收到过 ack——这就是所谓的"已确认但未落盘"空洞。

QuestDB 的 WAL 一旦出现这种空洞,重启后轻则丢最近几秒到几十秒的数据,重则需要人工介入修复 WAL 与列文件的一致性。对行情、交易、设备告警这类场景,这是不可接受的。

enterprise SSD 的 PLP 加断电电容就是为这一刻存在的,这也是我坚持时序库上 enterprise 盘的第一理由,顺序带宽反而排在第二位。租用机器时也要问一句:这台机器的 RAID 卡/主板有没有 BBU 或超级电容,写缓存策略是 WriteBack 还是 WriteThrough——WriteBack 无电池保护的组合,和一个没有 PLP 的消费级 SSD 是同一类风险。

DROP PARTITION 与按行 DELETE,代价差一个数量级

QuestDB 里清理历史数据有两条路:

ALTER TABLE ... DROP PARTITION:元数据层面的分区摘除加文件删除,毫秒到秒级完成,代价极低。这是按天/按月分区带来的最大收益,也是做数据保留策略(TTL)的正确姿势。

DELETE FROM ... WHERE ts < ...:要触及实际数据行,代价与命中行数成正比,在亿行级的表上跑几十分钟是常事,而且过程中产生大量额外写入,白白吃掉 SSD 寿命。

结论很直接:能按分区删,就不要按行删。反过来说,分区粒度一旦选错——比如选了 YEAR 又想按季度清理——这条最省事的路就彻底走不通了,后期只能靠按行 DELETE 硬扛。所以分区粒度要在建表那一刻就想清楚清理策略。

dedup 带来的是随机读,不是随机写

执行 ALTER TABLE ... DEDUP ENABLE UPSERT KEYS(ts, device_id) 之后,每次 commit 都要按 key 去已有数据里查一遍是否已经存在,这是典型的随机读负载,压力落在 4K 随机读 IOPS 和页缓存命中率上,而不是写 IOPS。

两个必须提前知道的代价:

吞吐要打折。开 dedup 之后写入性能下降非常明显,官方也明确提示有额外开销,实测常见打 3–7 折(非官方承诺值,与 key 数量和热窗大小强相关)。也就是说一台本来能写 50 万行/秒的机器,开 dedup 之后可能只剩 15–35 万行/秒。

去重效果与分区范围相关。如果你的重复数据是跨分区分布的,去重结果会和预期不一致。设计 UPSERT KEYS 之前先把重复数据的分布摸清楚。

我的判断:dedup 应该在"采集端确实无法保证不重发"时才开。如果上游消息队列(Kafka 之类)已经能按 key 做幂等,或者采集端有本地去重缓冲,就别让数据库扛这份随机读。数据库侧的 dedup 是最贵的一种去重,因为它发生在写入热路径上。

CPU 与并发账:向量化执行、写入线程抢核、压缩换空间的置换关系

向量化执行到底意味着什么

QuestDB 的 SQL 引擎按列批量处理,配合 SIMD 指令,单核扫几千万行/秒是常态。但这不等于"核越多单条查询越快"——7.x 起部分过滤算子支持并行执行,聚合、窗口函数这类算子仍受实现限制,单条 SQL 未必能把所有核吃满。

核数与吞吐的线性关系,更多体现在能同时跑多少条查询上。这一点决定了配核的思路不是"让一条 SQL 跑最快",而是"让峰值并发下的每条 SQL 都不排队"。

写入线程和查询线程怎么分核

一台跑 QuestDB 的机器上同时活着三类线程:ILP 写入线程(按连接数分配,可在 server.conf 里调 ILP worker 数)、WAL apply 工作线程(调 WAL apply worker 数)、查询执行线程。它们抢的是同一批核。

我的算法是这样的:

先估常驻查询并发——Grafana 面板轮询 + 定时报表 + 人工即席查询,峰值算 8 条并发 SQL;再加上写入侧 4 个线程(ILP 2 + WAL apply 2);合计 12,乘 1.3 留余量 ≈ 16 核,这就是起步配置。

有一个很实用的排查经验:写入 bursts 期间如果查询延迟突然飙升,多半是核被 WAL apply 线程占满,把 apply worker 数降下来往往比加核更快见效。因为把 apply 放慢只是让数据晚几秒可见,而查询延迟飙升会直接影响面板体验。

压缩换空间这笔账要不要做

文件系统级压缩(ZFS / btrfs)对时序数据的实际压缩率通常在 1.5–2.5 倍:时间戳和 symbol 列压缩率很高,double 型的测点数值基本压不动。代价是 CPU——lz4 单核压缩吞吐大约 200–500 MB/s(经验值/预估),也就是说每写入 300 MB/s 就要吃掉一个核左右。

三条取舍判断:

  • 磁盘容量不紧张、热窗内存才是瓶颈的场合,不要压。把核留给查询并发,比省那点磁盘划算。
  • 冷数据归档盘值得压。保存一年以上、查询极少的机器,本来就没有查询负载,核闲着也是闲着,压缩能实打实省下盘位和租金。
  • 用 ZFS 一定要给 ARC 设上限。ARC 和 mmap 的页缓存会形成两套缓存记账,两边互相挤,结果就是热窗命中率反而比不用 ZFS 还低。这是我见过最反直觉的一次"优化"。

一张表对上号:写入规模、热窗数据量、内存、SSD IOPS 与核数对照

典型场景 写入规模(行/秒) 日增数据量(12 B/行口径) 热窗数据量与建议内存 SSD 规格与 4K 随机写 IOPS 建议核数
小团队业务监控 1 万 ≈10 GB/天 7 天 ≈ 72 GB → 内存 128 GB 2×960 GB enterprise NVMe,稳态 ≥3 万 IOPS 8 核
中型 IoT 遥测 5 万 ≈52 GB/天 3 天 ≈ 155 GB → 内存 256 GB 4×1.92 TB enterprise NVMe,稳态 ≥8 万 IOPS 16 核
设备遥测 + 告警分析 20 万 ≈207 GB/天 1–2 天 ≈ 210–415 GB → 内存 512 GB 6×3.84 TB enterprise NVMe,稳态 ≥20 万 IOPS 32 核
行情 tick 落地 50 万 ≈518 GB/天 12 小时 ≈ 260 GB → 内存 512 GB–1 TB 8×3.84 TB enterprise NVMe,稳态 ≥30 万 IOPS 48 核
多实例分片集群 100 万+ ≈1.0 TB/天 6–12 小时 ≈ 260–520 GB/分片 → 每分片 512 GB,整机 1 TB 8×7.68 TB enterprise NVMe,稳态 ≥50 万 IOPS 64 核(双路)

表中数据量均为按 12 字节/行口径的估算值(预估),实际请以你自己表结构的实测行宽为准:把一周的数据写进去,用 du -sh 量一下分区目录大小,反除行数,得到真实行宽,再套回上面的算式。内存一列已经包含 1.5 倍余量与操作系统开销,可以直接拿去下单。

两处实测场景:行情 tick 落地与 IoT 遥测采集的配置差在哪

场景 A:行情 tick 落地——高列数、强乱序、热窗只有几小时

某券商量化团队的做法:单实例写 40 万行/秒,每行 8 个字段,按 DAY 分区,冷数据保留 90 天。他们的热窗其实很短——策略回测和实时监控只看最近 4–12 小时,但列数多、行宽压到 10 字节已经很紧,日增仍在 350 GB 左右。

这台机器的配置取舍很典型:内存只给了 512 GB(覆盖 12 小时热窗绰绰有余),但 SSD 堆到了 8 块 3.84 TB enterprise NVMe。因为行情数据源源不断、乱序比例在开盘集合竞价阶段能到 3–5%,重写压力比内存压力更现实。他们另外做了一件事:采集端做了 200 ms 的排序缓冲窗口,把乱序比例压到 0.5% 以下,重写量直接降了一个数量级——这比任何硬件升级都便宜。

场景 B:IoT 遥测采集——低列数、弱乱序、热窗按天算

某工业设备厂商:3000 台设备、每台 12 个测点、10 秒上报一次,算下来 3600 行/秒,日增约 4 GB。按 MONTH 分区,保留 3 年。

这台机器的配置完全相反:32 GB 内存就够了(一个月热窗 120 GB 也才刚需要加内存,实际他们查最近 7 天,7 GB 数据),两块 960 GB enterprise NVMe 做镜像,8 核。钱主要花在了可靠盘和双电源上,而不是堆内存和核数。这个场景最容易犯的错是"照抄别人的 256 GB 配置",结果内存常年闲置 90%,而真正该花钱的掉电保护和备份一件没做。

两个场景放一起看,结论很清楚:QuestDB 的配置没有通用解,热窗长度决定内存,乱序比例决定 SSD,并发数决定核数。把这三个数测出来,配置就自动出来了。

推荐配置:一万网络裸金属与云服务器怎么搭 QuestDB 节点

#1 一万网络「裸金属高内存型」——QuestDB 主力写入节点

时序库这种 mmap 密集、页缓存吃内存的负载,我一律推荐裸金属而不是云主机——不是因为云主机性能差,而是页缓存这件事必须在没有虚拟化层干扰的环境里才可控,而且裸金属能直接指定 enterprise SSD 型号和 RAID 卡电池,云主机这两项通常不透明。

一万网络深耕 IDC 19 年(成立于 2007 年),深圳自营机柜,裸金属标准档 E5-2698v4×2 / 32G / 1T 官网明示 ¥3999 起(以官网实时价为准)。QuestDB 场景要在这个基础上改配置:内存加到 256 GB 或 512 GB、系统盘换成 2×960 GB enterprise NVMe、数据盘按热窗配 4–6 块 3.84 TB NVMe,加配部分属定制项,价格以咨询为准(预估)。

几个对时序库特别有用的服务项:7×24 中文工单平均 5 分钟响应——写入卡住这种事半夜也会发生,工单响应速度比什么都实在;硬件故障 10 分钟自动迁移,SSD 是耗材,五年里总要坏一两块;免费系统盘快照(每日 3 份、30 秒回滚),升级 QuestDB 版本前先打一个快照,回滚成本几乎为零;工程师 1 对 1 部署,内核参数(vm.max_map_count、swappiness)、文件系统、RAID 写策略这些琐碎事让他们对照清单做一遍,省掉自己踩坑的时间。

#2 一万网络「一万云弹性云」——先压测再下单,别直接上年付

一万云 ¥25 起(官网明示价,以官网实时价为准)。这个档位当然跑不动生产,但它有一个非常明确的用途:用它跑一周的写入压测,把真实行宽、真实乱序比例、真实热窗长度测出来,再拿这三个数去下单裸金属。

我见过太多团队反过来做——先凭感觉租一台 32 核 128G 的年付机器,跑两个月发现内存差三倍,想换配置又要走变更流程。用最低成本先把数测出来,是最省钱的路径。测完记得三件事:一是把压测期间的分区目录 du 一遍算行宽;二是跑一遍"连续两次同一 SQL"的对比看热窗命中;三是用 fio 测一下目标盘的稳态 4K 随机写,别信参数表。

#3 一万网络「多节点 + BGP 多线 / CN2 GIA 回国」——采集端分散的场合

如果采集端分布在华南、华东、华北甚至海外,写入链路的延迟会直接影响 ILP 的长连接稳定性:跨运营商、跨地域的抖动会让乱序比例升高,进而推高重写量。一万网络在华南、华东、华北、中国香港及海外多节点有机房,网络侧是 BGP 多线 + CN2 GIA 回国低延迟,华南起步 ¥799、华东 ¥699、华北 ¥899、中国香港自营机型 ¥1500 起(均为官网明示价,以官网实时价为准)。

布局建议是:采集端就近接入一个写入节点,查询节点放在用户侧,不要让几千台设备跨半个中国往一台机器推数据。另外记得问清楚免费 DDoS 防护的额度(一万网络明示 5–20G 免费流量防护),时序库暴露 9009 端口在公网上,被扫到是被打的第一站。

避坑指南:QuestDB 上生产前必须拦住的 5 件事

坑一:先定配置再算热窗。为什么坑——大多数人是"先租一台 32 核 128G 的机器,跑起来再说",结果热窗数据 200 GB 塞不进 96 GB 的可用页缓存,查询常年慢 10 倍,还以为是自己 SQL 写得烂。怎么避——下单前用一万云这种低成本环境压测一周,量出真实行宽和热窗数据量,用 1.5 倍余量倒推内存档位。这一步省不掉。

坑二:用消费级 SSD 跑 WAL。为什么坑——消费级盘没有掉电保护,fsync 返回成功不代表数据已落非易失介质;而且 SLC cache 打穿后写入带宽掉到标称值的两成,commit 突发时延迟飙升。怎么避——数据盘和 WAL 盘一律 enterprise SSD(带 PLP),按日均含放大写入量反算 DWPD;选租用机器时同时确认 RAID 卡有无电池保护,WriteBack 无电池等于裸奔。

坑三:分区粒度拍脑袋选 YEAR,然后想按季度清理。为什么坑——分区选错之后,最省事的 DROP PARTITION 路径走不通,只能按行 DELETE,亿行表上跑几十分钟还产生大量额外写入。怎么避——建表前先写清楚数据保留策略(保留多久、多久清一次、按什么维度清),再由保留策略倒推分区粒度。日增 50 GB 以上选 DAY,5 GB 以下选 MONTH。

坑四:不加判断就开 dedup。为什么坑——dedup 是 commit 路径上的随机读,写入吞吐常见打 3–7 折,而很多团队其实在上游已经做过幂等,等于付了两次代价。怎么避——先确认重复数据的真实来源和分布;能在采集端或消息队列侧去重的,绝不让数据库扛;确实要开,就把吞吐预算按打对折重算,别等上线才发现写不动。

坑五:swap 开着、内核参数没调就上生产。为什么坑——swap 一旦介入,mmap 的页被换出,查询退化成随机磁盘 IO,整机会进入"活着但慢 100 倍"的状态,比直接挂掉更难发现;vm.max_map_count 默认 65530 在分区数上来之后会顶死。怎么避——上线清单里固定三项:swapoff -a 或 vm.swappiness=1、vm.max_map_count ≥ 262144、文件系统用 XFS 或 ext4 并按 mmap 负载挂载(关 atime)。这三项写成部署脚本的一部分,别靠人记。

运维群里问得最多的 7 个 QuestDB 硬件问题

Q1:QuestDB 到底要不要很大的内存?我们日均才 20 GB 数据。

A1:不看日均,看热窗。日均 20 GB、但报表天天扫最近 30 天,热窗就是 600 GB,那就要 1 TB 内存;反过来日均 500 GB、但只查最近 4 小时,热窗 86 GB,128 GB 内存就够。判断方法很简单:把最常用的那条 SQL 的时间范围写出来,乘以日增数据量,再乘 1.5,就是内存档位。日均这个数字本身在 QuestDB 选型里几乎没有参考价值,它只决定磁盘容量。

Q2:为什么 top 里 QuestDB 进程只有 4 GB,机器却提示内存快满了?

A2:因为 QuestDB 用 mmap 读写列文件,映射进来的页归操作系统页缓存管,不计入进程 RSS。你看到的 4 GB 是 Java 堆和进程自身的元数据结构,那 100 多 GB 是 buff/cache 里的热窗数据。这是设计使然,不是内存泄漏。要看真实占用用 free -h 的 available 列,用 pcstat 看列文件的驻留比例。反过来,如果 buff/cache 长期很小,说明热窗根本没进缓存,这才是要警惕的信号。

Q3:ILP 写入卡在 20 万行/秒上不去,加带宽有用吗?

A3:大概率没用,先在机器本地压一次就知道了。常见的三个卡点:commit 太频繁(maxUncommittedRows 配得太小,每次 commit 都要 fsync)、每行字段太多(10 个字段和 3 个字段差 2–3 倍)、乱序比例高(触发分区重写)。按顺序排查:先把 maxUncommittedRows 提到 10 万–50 万行量级、maxCommitLag 给到几百毫秒,再看字段数能不能合并,最后统计一下乱序比例。这三步做完通常能翻倍。

Q4:SSD 一定要 enterprise 吗?消费级 NVMe 顺序写也有 3 GB/s。

A4:要。理由不是顺序带宽,是掉电保护和稳态表现。QuestDB 的 WAL 依赖 fsync 真落盘,消费级盘没有 PLP,断电时 DRAM 缓存里的写入会丢,而 OS 已经 ack 过了;另外标称 3 GB/s 是 SLC cache 里的数字,cache 打穿后常见掉到 300–600 MB/s,恰好被 commit 突发打中。寿命也是一笔账:日均 780 GB 写入,1 TB/600 TBW 的消费盘两年出头就把额度跑完,而 3.84 TB/DWPD=1 的 enterprise 盘只占 0.2 DWPD。

Q5:按天分区还是按月分区?

A5:按保留策略倒推,不要按习惯选。需要按天或按周清理历史数据的,选 DAY——DROP PARTITION 是元数据操作,毫秒到秒级;选了 YEAR 还想按季度清,就只能按行 DELETE,亿行表上跑几十分钟。量的参考线:日增 50 GB 以上选 DAY,日增 5 GB 以下选 MONTH(文件更少、句柄更省),中间看查询习惯。还要算一笔账:分区数 × 列数会换算成 mmap 区域数,分区太细要同步把 vm.max_map_count 提上去。

Q6:查询变慢了,第一件事该看什么?

A6:先做"连跑两次"测试——同一条聚合 SQL 跑两遍,如果第二次明显快很多,说明第一次基本都在落盘读,问题在内存(热窗没进页缓存,或者有别的查询把热页挤出去了),加内存或缩小热窗范围。如果两次一样慢,问题在 CPU 或 SQL 本身:看查询并发是不是把核吃满了,看有没有全表扫描。再下一步看是不是写入 bursts 期间变慢——那是 WAL apply 线程在抢核,把 apply worker 数降下来通常比加核见效快。

Q7:文件系统要不要开压缩?

A7:看这台机器是热节点还是冷节点。热节点(有实时查询负载、热窗内存才是瓶颈)不要压——时序数据实际压缩率通常只有 1.5–2.5 倍,而 lz4 每 200–500 MB/s 写入就要吃掉一个核,把核留给查询并发更划算。冷数据归档节点值得压,反正核闲着。用 ZFS 的话务必给 ARC 设上限,否则 ARC 和 mmap 页缓存两套记账互相挤,热窗命中率反而下降——这个反直觉的坑我见过不止一次。

QuestDB 批次 9974:先算热窗再算内存,顺序别反了

把四本账收拢成一句话:热窗决定内存,乱序决定 SSD,并发决定核数,而顺序必须是先测后买。QuestDB 不是"给多大内存都能跑"的数据库,它是"热窗进不去页缓存就慢一个数量级"的数据库——这个特性决定了它的容量规划必须从业务查询行为出发,而不是从硬件预算出发。

给一个可以直接执行的动作清单:花一周时间,用最低成本的环境把三个数测出来——真实行宽(du 分区目录除行数)、真实乱序比例(统计补传量与时间戳回退量)、真实热窗长度(把最常用的 SQL 时间范围抄下来)。有了这三个数,内存档位、SSD 规格、核数会自己跳出来,根本不需要问别人"该配什么"。

硬件侧我的立场很明确:内存宁可多一档,SSD 必须是带掉电保护的 enterprise 盘,核数按并发乘 1.3 留余量;压缩在热节点上不划算,冷节点上才做。这四条不跟着业务规模变,跟着业务规模变的是具体数字。

数据来源与口径说明(QuestDB 时序库服务器租用)

本文涉及的 QuestDB 行为描述(列存 + mmap 读写、按时间分区、WAL 顺序追加与 apply、ILP over TCP 默认端口 9009、commit 相关参数 maxUncommittedRows 与 maxCommitLag、乱序写入触发分区重写、DROP PARTITION 与按行 DELETE 的代价差异、dedup 在 commit 时的 key 查找开销)为对该数据库公开技术文档的归纳与作者在生产环境的实测总结,具体参数默认值与行为边界请以你所使用的 QuestDB 版本官方文档为准。

文中所有配置推算(热窗数据量、建议内存、4K 随机写 IOPS 档位、DWPD 与 TBW 折算、核数余量、压缩率与压缩 CPU 开销、ILP 实测吞吐区间)均为估算值(预估),基于 12 字节/行这一假设行宽,仅供选型参考,不构成性能承诺;实际数值请以你自身表结构、乱序比例与并发模型的实测结果为准。

价格数据来源为一万网络官网公开页面:https://www.idc10000.net/(裸金属服务器、一万云弹性云、大陆与海外节点起步价、服务与网络说明页)。其中裸金属 E5-2698v4×2 / 32G / 1T ¥3999 起、一万云 ¥25 起、华南 ¥799 起 / 华东 ¥699 起 / 华北 ¥899 起、中国香港自营机型 ¥1500 起为官网明示价,以官网实时价为准;内存升级、enterprise NVMe 更换、多节点组网等定制配置属非标项,价格以咨询为准(预估)。具体以签约时最新报价与合同为准。


上一篇:2026 服务器租用全解:Redmine 自建项目管理的并发、附件磁盘与数据库配置避坑

下一篇:2026 服务器租用手册:Delta Lake 湖仓 OPTIMIZE 与小文件合并,CPU/内存/磁盘三本账怎么算