一个索引到底占多大?字段长度和取值分布怎么影响它?前缀压缩有多重要?这篇用同一个 20 万文档的集合建 12 个不同字段的索引逐个量。
字段 值的类型 值的 BSON 字节 索引大小 每条目字节 i32 int32 递增 4.0 1,986,560 9.9 i64 int64 8.0 2,912,256 14.6 dbl double 随机 8.0 3,575,808 17.9 oid ObjectId 12.0 1,789,952 8.9 seq32 32 字符,按顺序递增 37.0 2,396,160 12.0 rnd32 32 字符随机十六进制 37.0 8,056,832 40.3 s8 8 字符随机 13.0 2,695,168 13.5 s16 16 字符随机 21.0 4,485,120 22.4 s64 64 字符随机 69.0 15,429,632 77.1 s128 128 字符随机 133.0 30,117,888 150.6 pre 60 字符,前 52 个相同 65.0 3,080,192 15.4 cat 4 个取值的枚举 9.2 1,077,248 5.4 _id_ (int 递增) 2,207,744 11.0 数据本身 storageSize 68,308,992;所有索引合计 79,810,560
枚举 5.4 字节、ObjectId 8.9、int32 9.9、递增字符串 12.0、随机 32 字符 40.3、随机 128 字符 150.6 字节。字段类型和取值分布共同决定大小。
seq32 2,396,160 字节;rnd32 8,056,832 字节(是顺序递增的 3.4 倍) pre(60 字符,前缀 52 相同)3,080,192 字节;s8(8 字符随机)2,695,168 字节;s64(64 字符随机)15,429,632 字节
WiredTiger 默认对索引做前缀压缩:顺序递增的字符串索引只有同样长度随机字符串的 1/3.4;前 52 个字符相同的字符串也压得很好。
8 字符:每条目 13.5 字节 16 字符:每条目 22.4 字节 32 字符:每条目 40.3 字节 64 字符:每条目 77.1 字节 128 字符:每条目 150.6 字节 从 8 到 128 字符,每多 1 个字符,每条索引条目平均多 1.14 字节
随机字符串每多一个字符,每条索引条目平均多约 1.14 字节;长字段上的索引非常大。
seq32_1:有前缀压缩(默认)2,396,160 字节;prefix_compression=false 8,736,768 字节(是默认的 3.6 倍) pre_1:有前缀压缩(默认)3,080,192 字节;prefix_compression=false 15,261,696 字节(是默认的 5.0 倍)
建索引时指定 prefix_compression=false,seq32 索引变大 3.6 倍,pre 索引变大 5.0 倍。
复合 {cat, rnd32} 8,458,240 字节;单字段 cat 1,077,248 + rnd32 8,056,832 = 9,134,080 字节{cat, rnd32} 复合索引比 cat 与 rnd32 两个单字段索引合计小约 7%。
50,000 个文档:2,035,712 字节(每条目 40.7 字节) 100,000 个文档:4,046,848 字节(每条目 40.5 字节) 200,000 个文档:8,056,832 字节(每条目 40.3 字节)
索引大小随文档数线性增长,每条目字节数基本不变。