想象你是一座城市排水监控中心的负责人,成千上万个雨量计、水位计每秒都在向你递来小便条:“东城区立交桥,水位 1.2 米,10:00:01”;“西城区隧道,水位 0.8 米,10:00:01”。这些便条不是一天一份周报,而是永不停歇的连续消息。如果按普通办公文件的整理方式存放,很快你的档案室就会被塞满,找一条“过去五分钟东城区哪些桥洞积水超阈值”也要翻遍所有抽屉。 InfluxDB 就是为这类问题设计的“智能档案库”。它属于时序数据库,也常和 NewSQL、新型存储放在同一个展厅里:不追求万能的事务能力,只想把“带时间戳的数据”存得快、压得小、查得准。档案袋上贴的彩色标签叫 tag,袋里装的数值叫 field,盖上的日期叫 timestamp;而底层的 TSM 存储引擎,则像一套聪明的归档流水线:新便条先放在临时收件台,写一本登记簿,满了就封箱归档,后台再定期合并旧箱子,腾出空间。

岗位关联

掌握 InfluxDB 的数据模型与 TSM 引擎思想,你就能在物联网、监控运维这类高频写入场景中,从“存不下、查不动”走向“存得稳、查得快”。

目录
  1. 可视化演示
  2. 时序数据特征
  3. 数据模型基础
  4. 标签索引设计
  5. 时间分片机制
  6. TSM引擎基础
  7. 列式存储压缩
  8. 写入合并流程
  9. 查询优化思路
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

时序数据特征

排水监控中心的雨量计不是“每隔一周交一份周报”,而是每一秒都递来一张小天条。一分钟积累六十条,一台设备一天就是八万六千多条;整座城市有上万台设备,数据量会像暴雨后的积水一样迅速上涨。更关键的是,这些数据几乎不会回头修改:传感器只追加新记录,很少去更新昨天那条水位值,这是一种典型的“顺序追加型写入”。

如果把时序数据当成银行账户流水来管理,数据库会为随机更新付出大量锁和索引开销;但这里的数据天然按时间排列,查询也天然带着时间范围:“三分钟前”“最近一小时”“上周二”。于是 InfluxDB 把时间戳当作第一公民,围绕时间轴来组织一切。数据越新越常被访问,越老越少被访问,形成明显的冷热分层,这为后续的分片和压缩提供了线索。

规划存储规模时,可以先做一个简单估算:

一旦理解了这种高频、海量、按时间聚合的数据特征,就能明白 TSM 存储引擎为什么要把“批量顺序写”和“时间分片”作为头等大事——不是偶然选择,而是被数据形态逼出来的。

Npoints=D×F×T\displaystyle N_{\text{points}} = D \times F \times T
这个公式告诉你:总数据点约等于设备数、采集频率和保留时长的乘积。
  1. 设备数 D城市里接入的监测点数量,例如一万个传感器。
    DD
  2. 采集频率 F每个传感器每秒或每分钟上报几条记录。
    FF
  3. 保留时长 T数据需要保存的时间跨度,例如 30 天。
    TT
  4. 总点数 N三者相乘得到存储规模的下界。
    Npoints=D×F×TN_{\text{points}} = D \times F \times T

数据模型基础

档案室的每一条雨水记录都装在一个信封里:信封正面写明它属于哪个档案柜,这是 measurement;信封上贴着五颜六色的标签,用于快速检索,这是 tag;信封里装的实测数据,这是 field;信封右上角的邮戳时间,则是 timestamp。InfluxDB 中一条 point,就是这样一个完整信封。

measurement 相当于关系数据库里的表,例如 rain;tag 是键值对,如 area=east、type=bridge,它默认被建索引;field 也是键值对,如 level=1.2、temperature=23.5,保存真正的测量值,默认不建索引;timestamp 是纳秒级时间戳,与 tag 一起决定这条数据“属于哪个序列的哪个时刻”。

这个数据模型可以浓缩成一个式子:

把四者拆开,InfluxDB 就能在写入时知道该给哪些内容建索引、把哪些内容送去压缩,而不会像普通表格那样对每一列都一视同仁。

point=(measurement, tag_set, field_set, timestamp)\displaystyle \text{point} = (\text{measurement},\ \text{tag\_set},\ \text{field\_set},\ \text{timestamp})
看懂这条公式,就掌握了 InfluxDB 的“一封信”由哪四个部分组成。
  1. measurement档案柜的名字,对应一类测量对象。
    measurement\text{measurement}
  2. tag\_set一组可索引的标签键值对,负责回答“是谁的数据”。
    tag_set={k1=v1, k2=v2,… }\text{tag\_set}=\{k_1=v_1,\ k_2=v_2,\dots\}
  3. field\_set一组实际数值,负责回答“数据值是什么”。
    field_set={f1=a1, f2=a2,… }\text{field\_set}=\{f_1=a_1,\ f_2=a_2,\dots\}
  4. timestamp这条记录发生的时间戳,负责回答“什么时候发生”。
    timestamp\text{timestamp}

标签索引设计

档案管理员要回答“东城区所有立交桥的积水记录”,不会挨个打开档案盒翻。他会先看一本标签台账:area=east 指向一批序列,type=bridge 指向另一批序列,两批求交集,就能迅速锁定候选档案盒。这本台账,就是 InfluxDB 的倒排索引。

倒排索引的思路是:为每个标签值建立一条“哪些序列包含这个标签值”的列表。例如 floor=3 对应序列 A、B、C,host=web-2 对应序列 B、D。查询时先通过标签定位序列,再结合时间范围扫描具体数据块,而不是从第一条记录开始遍历。

查询条件组合可以看作集合的交运算:

标签设计不能贪多:如果给每个设备唯一编号都做成标签,基数会爆炸,倒排索引占用的内存也会疯涨。所以 InfluxDB 社区的黄金法则是:低频变化、常作为查询条件的放 tag;高频变化、不需要索引的数值放 field。

S=Sarea=east∩Stype=bridge\displaystyle S = S_{\text{area=east}} \cap S_{\text{type=bridge}}
一个查询条件就是一个集合,多个标签条件做交集,得到候选序列集合。
  1. 标签值集合 Sarea=east 这个标签值命中的所有序列集合。
    Sarea=eastS_{\text{area=east}}
  2. 另一个标签值集合type=bridge 命中的所有序列集合。
    Stype=bridgeS_{\text{type=bridge}}
  3. 交集运算符两个集合取重叠部分。
    ∩\cap
  4. 结果集 S同时满足两个标签条件的序列集合。
    S=Sarea=east∩Stype=bridgeS = S_{\text{area=east}} \cap S_{\text{type=bridge}}

时间分片机制

档案室不会把所有年份的档案混在一个大仓库,而是按月装箱:1 月一个货架区,2 月一个货架区。这样要查“上周二”的记录,只需走进对应的一个月盒,而不是把十年档案都翻一遍。InfluxDB 的 shard(分片)就是这种“时间箱”。

每个 shard 覆盖一个确定的时间区间,例如 7 天。在一个 shard 内部,数据按序列组织,并对应一组 TSM 数据文件。保留策略(retention policy)的删除也以 shard 为单位:数据过期时,直接丢弃整个 shard,而不是逐条删除记录,这让清理成本极低。

一个数据库会有多少个 shard,可以用除法估算:

分片不能拍脑袋定大小:太小会产生大量小文件,太大又会让查询扫过太多无关数据。实际部署时通常结合写入速率、查询时间范围和保留策略共同决定。

num_shards=retention_durationshard_duration\displaystyle \text{num\_shards} = \frac{\text{retention\_duration}}{\text{shard\_duration}}
保留时长除以单个分片时长,就是系统里大致存在的分片数量。
  1. 总保留时长例如 30 天。
    retention_duration=30\text{retention\_duration}=30
  2. 单个分片时长例如 7 天。
    shard_duration=7\text{shard\_duration}=7
  3. 相除取商得到分片数量。
    307≈4\frac{30}{7}\approx4
  4. 结果意义系统大约维护 4 个 shard,旧 shard 整片淘汰。
    num_shards\text{num\_shards}

TSM引擎基础

档案室的收件系统有一条流水线:新送来的便条先放到“临时收件台”上,同时登记员在一本“收件登记簿”上写一笔,防止便条丢失;当收件台堆满后,工作人员把它们按时间排好序,封进一个只读的“档案砖”;以后档案砖积累多了,再被后台合并成大砖。这就是 TSM 引擎的骨架,也是 LSM 树思想在时序数据上的变体。

LSM 树的核心智慧是:把昂贵的随机写变成廉价的顺序写。数据先写内存结构,达到阈值后一次性刷到磁盘,生成不可变文件;后续查询需要读多层文件,因此还要定期合并,减少数据版本。InfluxDB 的 TSM 文件继承了这种“先攒批,再落盘”的节奏,但每个文件内部不是普通键值对,而是按时间序列组织的列式数据块。

为什么 LSM 宁愿多做合并,也要坚持顺序写?因为磁盘随机访问的代价远大于顺序访问:

理解了这套“先内存、再落盘、后合并”的节奏,再看 TSM 的 WAL、快照和压缩流程,就不会觉得它们是零散技巧,而是同一思想的不同环节。

Crandom≈seek+transfer≫Csequential≈transfer\displaystyle C_{\text{random}} \approx \text{seek} + \text{transfer} \quad \gg \quad C_{\text{sequential}} \approx \text{transfer}
随机读写多一次寻道,而顺序读写基本只需要转移数据,两者差距可达数量级。
  1. 寻道时间磁盘或 SSD 移动到目标位置的开销。
    seek\text{seek}
  2. 传输时间真正读写数据块的时间。
    transfer\text{transfer}
  3. 随机访问成本每次都要寻道加上传输。
    Crandom≈seek+transferC_{\text{random}} \approx \text{seek} + \text{transfer}
  4. 顺序访问成本连续读写基本免去反复寻道。
    Csequential≈transferC_{\text{sequential}} \approx \text{transfer}
  5. 远大于关系这正是 TSM 选择批量顺序写的原因。
    ≫\gg

列式存储压缩

普通档案室会把一份报告的日期、地点、数值、备注都放在同一张纸上;而 TSM 档案室更聪明:它把同一段时间内同一种数值单独装订成册。比如把一万个传感器在五分钟内的水位值单独列成一张表,而不是和温度、湿度混在一起。这种“按列集中存放”的布局,让压缩算法能发现更多规律。

时序数据最有规律的字段是时间戳:同一序列的时间戳严格递增,相邻差值往往很小且稳定。于是 InfluxDB 不直接存储完整时间戳,而是存储相邻时间戳的差值,用更少的字节表达同样的信息;如果差值重复出现,还能进一步用游程编码压缩。

一次典型的差分编码是这样的:

列式布局加差分编码,是 TSM 磁盘占用低的关键。这也是为什么它擅长处理“很多传感器、每隔几秒写一条”的场景:数据规律越强,压缩率越高。

Δi=ti−ti−1\displaystyle \Delta_i = t_i - t_{i-1}
把绝对时间戳换成相对前一个时间戳的差值,大幅减少数值的取值空间。
  1. 当前时间戳序列中第 i 条记录的时间。
    tit_i
  2. 前一条时间戳第 i-1 条记录的时间。
    ti−1t_{i-1}
  3. 取差记录相邻时间差,而不是完整时间。
    Δi=ti−ti−1\Delta_i = t_i - t_{i-1}
  4. 进一步压缩当差值序列出现大量相同值时,用游程压缩把它写成更短的标记。
    RLE(Δ1,Δ2,… )\text{RLE}(\Delta_1, \Delta_2, \dots)

写入合并流程

档案室的收件流程有明确顺序:便条到达后,登记员先在“收件登记簿”(WAL)上写一笔,再把便条放在临时收件台(内存缓存)。这样做的好处是,即使档案馆突然停电,也能靠登记簿找回还没归档的便条。当收件台放满到阈值,工作人员便把台面上的便条按时间排好序,封进一个新的 TSM 档案砖。

此后,后台的合并程序会周期性检查档案砖数量。小砖太多,查询就要读太多文件,所以合并程序把多个小砖合并成大砖,同时清理已经被标记删除的旧数据。这个“合并”动作不是随手做,而是有触发条件的。

内存缓存何时刷盘,可以写成:

每个 TSM 文件还带一份稀疏索引,记录数据块的最小、最大时间和序列范围。查询时先看这份“目录”,能直接跳过无关文件和数据块,避免全文扫描。

flush  ⟺  sizecache≥threshold\displaystyle \text{flush} \iff \text{size}_{\text{cache}} \ge \text{threshold}
当缓存大小达到阈值时,触发一次不可逆的刷盘操作,生成只读 TSM 文件。
  1. 缓存大小当前正在积累的写入数据量。
    sizecache\text{size}_{\text{cache}}
  2. 触发阈值管理员设定的缓存上限。
    threshold\text{threshold}
  3. 比较条件达到或超过上限时条件成立。
    sizecache≥threshold\text{size}_{\text{cache}} \ge \text{threshold}
  4. 触发动作刷盘并生成新 TSM 文件。
    flush\text{flush}

查询优化思路

现在回到最开始的难题:找出东城区所有立交桥过去五分钟水位超过一米二的点。聪明的档案管理员不会搬出整座档案库,而是执行三步:先查标签台账,锁定“东城区”和“立交桥”对应的序列;再查每个时间箱的封面,只打开最近五分钟那个 shard;最后在 TSM 文件里,只看水位这一列的数据块,而不是把湿度、温度也全读出来。

这套流程对应 InfluxDB 的查询优化:时间范围裁剪负责跳过过期 shard,标签过滤负责缩小序列集合,列式存储让系统只解压需要的字段,聚合下推则把最大值、平均值等计算尽量下沉到数据块层面。

一次查询的耗时可以粗略拆解为:

所以,设计表结构时多花心思选好标签、定好分片时长,实际上是在为查询优化铺路:让系统能跳过更多文件、解码更少数据,最终用更短时间回答“过去五分钟发生了什么”。

Tquery≈Tscan+Tdecode+Taggregate\displaystyle T_{\text{query}} \approx T_{\text{scan}} + T_{\text{decode}} + T_{\text{aggregate}}
查询时间大约等于扫描数据块的时间、解码压缩块的时间和聚合计算的时间之和。
  1. 扫描时间定位并读取候选数据块的时间。
    TscanT_{\text{scan}}
  2. 解码时间把压缩后的列式块还原成可计算数值的时间。
    TdecodeT_{\text{decode}}
  3. 聚合时间在多个时间分片上执行求和、最大、均值等操作的时间。
    TaggregateT_{\text{aggregate}}
  4. 总和三者相加,就是用户感知的查询延迟。
    Tquery≈Tscan+Tdecode+TaggregateT_{\text{query}} \approx T_{\text{scan}} + T_{\text{decode}} + T_{\text{aggregate}}

AI 应用场景

工业设备振动监测

阶段:数据采集与存储

解决的问题:传统方式把传感器数据写入关系数据库,高频写入会把索引拖垮,查询“最近一小时哪些轴承振动超标”也很慢。InfluxDB 用 tag 记录设备编号和工位,用 field 记录振动值,按时间 shard 存储,AI 模型可以快速拿到最近窗口的特征数据。

具体案例:一条汽车生产线每分钟产生 200 万条振动记录。使用 InfluxDB 后,写入吞吐提升,异常检测模型只需查询最近 5 分钟振动均值和峰值,即可实时判断刀具磨损状态。

可观测性指标中心

阶段:指标聚合与存储

解决的问题:微服务架构下,CPU、内存、延迟、QPS 指标量巨大,且每个服务都有多个实例和标签。用 InfluxDB 的 tag 记录服务名、实例 IP、区域,用 field 记录指标值,查询时按时间范围裁剪并下推聚合,显著降低监控告警系统的延迟。

具体案例:某电商平台将每秒上报的 800 万个指标点写入 InfluxDB,通过 mean、p99 等聚合下推,大促时的监控 Dashboard 能保持在秒级刷新。

新能源电池状态跟踪

阶段:时序特征存储

解决的问题:动力电池在充电、放电过程中电压、温度、电流随时间变化,需要长期保存并做寿命预测。InfluxDB 的 TSM 压缩能大幅降低存储成本,保留策略自动淘汰过期数据,AI 模型可基于历史电压曲线预测电池健康度。

具体案例:某换电站为每块电池建立独立序列标签,记录每次充放电的完整曲线,并通过差分压缩把磁盘占用降低 70%,模型训练时按车辆 ID 和时间窗快速抽取数据。

Python 演示

python64 行
from collections import defaultdict  class Point:    def __init__(self, measurement, tags, fields, ts):        self.measurement = measurement        self.tags = tags        self.fields = fields        self.ts = ts     def to_line(self):        tag_str = ",".join(f"{k}={v}" for k, v in sorted(self.tags.items()))        field_str = ",".join(f"{k}={v}" for k, v in sorted(self.fields.items()))        return f"{self.measurement},{tag_str} {field_str} {self.ts}"  class MiniTSM:    def __init__(self, max_mem=4):        self.max_mem = max_mem        self.mem_count = 0        self.segments = []        self.series_index = defaultdict(set)     def write(self, point):        self.mem_count += 1        key = point.measurement + "|" + ",".join(f"{k}={v}" for k, v in sorted(point.tags.items()))        self.series_index[key].add(point.ts)        if self.mem_count >= self.max_mem:            self.flush()     def flush(self):        self.segments.append(self.mem_count)        self.mem_count = 0     def compact(self):        if len(self.segments) >= 3:            total = sum(self.segments)            self.segments = [total]     def query(self, measurement, tag_query, start, end):        hits = []        key = measurement + "|" + tag_query        for point_ts in self.series_index.get(key, []):            if start <= point_ts <= end:                hits.append(point_ts)        return hits  def main():    engine = MiniTSM(max_mem=4)    p1 = Point("rain", {"area": "east", "type": "bridge"}, {"level": 1.2}, 100)    p2 = Point("rain", {"area": "east", "type": "bridge"}, {"level": 1.5}, 200)    p3 = Point("rain", {"area": "west", "type": "road"}, {"level": 0.8}, 150)    p4 = Point("rain", {"area": "east", "type": "bridge"}, {"level": 2.1}, 300)    for p in (p1, p2, p3, p4):        engine.write(p)        print("write:", p.to_line())    engine.compact()    print("segments:", engine.segments)    print("query:", engine.query("rain", "area=east,type=bridge", 100, 250))  if __name__ == "__main__":    main()
目的:用不到一百行实现一个简化版“内存缓存 + 倒排索引 + 刷盘 + 合并”的迷你 TSM 引擎,演示 InfluxDB 的写入与查询流程。
  1. key = point.measurement + "|" + ",".join(f"{k}={v}" for k, v in sorted(point.tags.items()))把表名和排序后的标签拼接成序列键,保证相同标签集一定对应同一个索引项。
  2. self.series_index[key].add(point.ts)在倒排索引中记录该序列出现过的所有时间点,等价于标签台账。
  3. if self.mem_count >= self.max_mem:内存计数达到阈值,触发一次刷盘。
  4. self.segments.append(self.mem_count)把当前内存中的记录数封存为一个只读段,模拟 TSM 文件生成。
  5. if len(self.segments) >= 3:小段数量达到三个,就触发合并,模拟后台 compact。

常见误区

误区初学者常认为“标签和字段都是键值对,放哪里都一样,随便选就行”。

正解标签会进入倒排索引,负责过滤和定位;字段不建索引,只负责数值存储和压缩。如果想把一个唯一设备 ID 做成标签,会产生极高的序列基数,让索引内存暴涨。正确做法是把高频查询条件放标签,把高基数或纯粹数值放字段。

为何常见:从关系数据库转过来的人习惯“每个列都能建索引”,容易忽略时序数据中标签是一种轻量级元数据,而不是通用列。

误区有人以为 InfluxDB 直接用 LevelDB 那套 LSM 实现,TSM 只是换了个文件后缀。

正解TSM 虽然继承 LSM 的“内存缓冲 + 不可变文件 + 合并”框架,但它针对时间序列做了专门改造:文件内部按序列和列式块组织,时间戳做差分编码,数值按类型做专用压缩。它不是通用键值存储,而是按时间轴优化的列式 LSM 变体。

为何常见:LSM 和 TSM 的英文缩写太像,加上很多文章只讲 LSM 思想,容易让人忽略文件内部结构的巨大差异。

误区初学者觉得分片越细,查询裁剪得越精确,所以把 shard 时长设成 1 小时甚至更短。

正解分片太细会产生大量小文件和索引对象,写入和合并开销反而上升;分片太粗又会让一次查询扫描过多无关数据。合理做法是结合写入速率、保留时长和典型查询窗口,通常选择 7 天或 1 天作为 shard 时长。

为何常见:人被“精确裁剪”带来的好处吸引,却忽略了元数据数量、文件数量这些成本也是真实存在的。

误区有人认为只要把数据排成列,再调用 gzip 压缩一次,就能达到 InfluxDB 的压缩率。

正解TSM 的高压缩率来自对数据语义的理解:时间戳相邻差分、浮点数专用压缩、游程编码处理重复值。通用压缩算法无法利用这些时序规律,往往压缩慢且效果一般。

为何常见:大家熟悉“列存 + 压缩”的组合拳,却忘了列存提供的是可压缩性,真正的压缩收益来自编码方式与数据分布匹配。

面试题

Q1. InfluxDB 中用于建立索引的是?

单选题 · easy

  • A.标签键值对← 正确答案
  • B.字段键值对
  • C.数据库名称
  • D.表结构定义

答案:A。标签会进入倒排索引,用于快速过滤;字段只保存数值,默认不建索引。这和普通数据库“每个列都可以建索引”的习惯不同,是时序模型的核心设计。

Q2. WAL 日志的主要作用是?

单选题 · easy

  • A.加速磁盘压缩
  • B.崩溃时恢复数据← 正确答案
  • C.替代内存缓存
  • D.提升查询速度

答案:B。WAL 是“收件登记簿”,写入时先记日志再进缓存,一旦进程崩溃,可以用它恢复尚未刷盘的数据。它不负责压缩、缓存或查询加速。

Q3. InfluxDB 中一个 point 的唯一性由什么决定?

单选题 · mid

  • A.表名加标签集加时间戳← 正确答案
  • B.表名加字段集加时间戳
  • C.标签集加字段集加库名
  • D.只有时间戳一个值

答案:A。同一 measurement 下,相同标签集构成一个时间序列,序列内由时间戳区分不同 point。字段值不参与唯一性判断,因此两条记录即使字段不同,只要序列名和时间戳相同,仍视为同一点。

Q4. 列式存储的主要优点是什么?

单选题 · mid

  • A.同类数据同列← 正确答案
  • B.行间事务更强
  • C.单行写入更快
  • D.天然支持外键

答案:A。列式存储把同一字段的连续值放在一起,方便使用差分、游程等编码压缩。它并不天然增强事务、外键或单行写入性能,反而会牺牲随机单行更新的能力。

Q5. flush 后的 TSM 文件为什么设计成只读?

单选题 · hard

  • A.避免随机覆写← 正确答案
  • B.节省内存空间
  • C.保证数据加密
  • D.方便用户编辑

答案:A。只读文件可以放心地顺序合并、批量重写,不需要处理原地更新的随机写;这正是 LSM 思想中“用批量顺序写换性能”的体现,而不是为了加密或节省内存。

Q6. 时间戳差分编码的核心思路是?

单选题 · hard

  • A.记录相邻差值← 正确答案
  • B.记录完整原值
  • C.转为字符串存储
  • D.按字典序排序

答案:A。同一序列的时间戳紧密递增,完整时间戳取值空间很大,而相邻差值通常很小。把差值用变长编码存储,可以显著减少字节数;差值序列出现重复时还能配合游程压缩。

Q7. 时序数据的冷热分层主要依据是什么?

单选题 · easy

  • A.数据时间新旧← 正确答案
  • B.标签数量多少
  • C.字段类型长短
  • D.写入并发大小

答案:A。最新数据被查询频率最高,越旧的数据越少被访问,因此按时间新旧区分冷热。保留策略删除过期数据时,也直接丢弃整个旧 shard,而不是按照标签或字段类型清理。

Q8. 下列哪些属于 InfluxDB 标签设计的合理原则?

多选题 · mid

  • A.高频筛选放标签← 正确答案
  • B.低基数放标签← 正确答案
  • C.高基数放字段← 正确答案
  • D.一切数据放标签

答案:ABC。标签会被倒排索引加载到内存,因此只适合放低频变化、常作为查询条件的键。设备 ID、用户 ID 这类高基数数据应放入 field,否则会撑爆索引内存。选项 D 会把所有数据都变成索引,明显错误。

Q9. TSM 文件在合并操作中会做什么?

多选题 · hard

  • A.合并零散文件← 正确答案
  • B.重写列式块← 正确答案
  • C.清除删除标记← 正确答案
  • D.回滚全部写入

答案:ABC。后台 compaction 把多个小 TSM 文件合并成大文件,重写内部列式数据块,并清理已被标记删除的数据。它不会回滚新写入,只负责让数据在物理上更紧凑。

Q10. 查询优化中“时间范围裁剪”为什么有效?

多选题 · hard

  • A.数据按时间分片← 正确答案
  • B.文件记录时间范围← 正确答案
  • C.跳过无关分片← 正确答案
  • D.不需要读取索引

答案:ABC。InfluxDB 按时间把数据划入不同 shard,每个 TSM 文件还记录最小、最大时间。查询时可以先跳过不包含目标时间范围的分片和文件,因此裁剪有效。但这不等于不读取索引,标签过滤仍然需要索引参与。