为查询性能划分 S3 数据
您将为 S3 路径定义分区属性,使 Data Federation 能够剪除无关文件并快速提供分析查询结果。
为查询性能划分 S3 数据 是 CoddyKit 上的免费 MongoDB Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 MongoDB Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 MongoDB Academy 课程共包含 4 节课。
为什么 S3 数据分区很重要
在 Atlas Data Federation 中,针对由 S3 支持的虚拟集合执行的每个查询都可能读取大量文件。如果没有分区,即使查询只请求某一天的数据,也可能扫描整整一年的文件。分区会将 S3 对象组织成目录结构,并在路径中编码可查询的元数据,使查询引擎能够跳过无关文件,这种技术称为分区裁剪。
分区裁剪:核心机制
分区裁剪之所以有效,是因为 Atlas Data Federation 会解析 S3 对象键(路径),并提取存储配置中定义为分区属性的值。当查询筛选条件与其中一个属性匹配时,查询引擎只读取路径值匹配的对象,跳过所有其他对象,甚至不会为这些对象发出 S3 GetObject 请求。
// Path template with partition attributes
// /events/{year int}/{month int}/{day int}/data.parquet
// Query: fetch March 15, 2025 data
db.events.find({ year: 2025, month: 3, day: 15 })
// Data Federation issues S3 ListObjects only for:
// /events/2025/3/15/
// All other years/months/days are skipped设计分区结构
请根据查询筛选数据的方式选择分区属性。常见模式包括:对于时间序列数据,使用基于时间的属性(年/月/日);对于全球数据,使用基于地理位置的属性(区域/国家);对于多租户 SaaS,使用基于实体的属性(tenantId、userId)。请将最常用于筛选的分区属性放在层次结构的最高层,以实现最大的裁剪效果。
// Time-based partition hierarchy
// /events/{year int}/{month int}/{day int}/{hour int}/
// Entity + time partition (tenant queries prune all other tenants)
// /orders/{tenantId string}/{year int}/{month int}/
// Geo + time
// /events/{region string}/{year int}/{month int}/在存储配置中注册分区属性
分区属性会在存储配置的 path 字段中声明,使用包含属性名称和类型的花括号语法:{attrName type}。支持的类型包括 string、int 和 ISODate。类型决定了属性如何解析,以及如何与查询筛选值进行比较。
{
'dataSources': [{
'storeName': 's3Store',
'path': '/events/{year int}/{month int}/{day int}/*.parquet'
}]
}
// Partition attributes: year (int), month (int), day (int)
// Filters like { year: 2025, month: 3 } trigger pruning
// The '*.parquet' at the end matches any file in the day directory文件大小:找到最佳范围
分区裁剪作用于目录级别,但文件大小同样重要。过多的小文件(数千个 1 KB 文件)会浪费时间,即使完成裁剪,也需要为每个文件调用 S3 API。过少的大文件(每月一个 100 GB 文件)又会导致无法在月份级别以下进行裁剪。请将文件大小控制在 64 MB 到 256 MB(压缩后),并确保每个分区包含足够的文件,以便在需要时启用子分区裁剪。
// Ideal partition design for daily query patterns:
// /events/2025/03/15/part-001.parquet (~128 MB each)
// /events/2025/03/15/part-002.parquet
// /events/2025/03/15/part-003.parquet
// Total: ~384 MB for a busy day, 3 files to manage
// Avoid:
// /events/2025/03/15/00001.json (1 KB each, thousands of files)
// /events/2025/march.parquet (no day-level pruning possible)使用 ISODate 分区属性
对于在路径中以 ISO 格式编码时间戳的 S3 路径(例如:2025-03-15),请使用 ISODate 分区属性类型。这样,您就可以使用 MongoDB 日期比较运算符($gte、$lt、$lte)针对分区属性进行筛选,Data Federation 也会正确裁剪请求日期范围之外的文件。
// Path: /events/{date ISODate}/data.parquet
// e.g.: /events/2025-03-15/data.parquet
// Query with ISODate range — triggers pruning
db.events.find({
date: {
$gte: ISODate('2025-03-01'),
$lt: ISODate('2025-04-01')
}
})
// Only reads /events/2025-03-*/ directories压缩和重新分区文件
随着时间推移,流式数据管道通常会生成许多小文件(即“小文件问题”)。为了保持查询性能,请定期压缩文件:读取一个分区中的所有文件,然后将它们重新写入为数量更少、大小更大的文件。通常可以使用 Spark、AWS Glue,或使用计划运行的 Atlas Function 读取并重新导出数据来完成此操作。
// Compact using MongoDB Data Federation's own $out
// (Re-export a partition to a temporary location, then replace)
db.events_raw.aggregate([
{ $match: { year: 2024, month: 1 } },
{ $out: {
s3: {
bucket: 'mycompany-analytics-archive',
region: 'us-east-1',
filename: 'events/2024/1/compacted-{UUID()}.parquet',
format: { name: 'parquet' }
}
}}
])使用 $out 将数据导出到 S3
Data Federation 支持 $out 的扩展形式,可将聚合结果直接写入 S3,而不是 Atlas 集合。它用于 ETL 管道:从 Atlas 读取原始数据,对其进行转换,然后以优化格式(Parquet、BSON)将结果导出到 S3,供将来的联合查询或下游分析工具使用。
// Export to S3 in Parquet format from Atlas
db.orders.aggregate([
{ $match: { year: 2025, month: 3 } },
{ $project: { customerId: 1, amount: 1, region: 1, status: 1 } },
{ $out: {
s3: {
bucket: 'mycompany-analytics-archive',
region: 'us-east-1',
filename: 'orders/2025/3/data.parquet',
format: { name: 'parquet', maxFileSize: '128MB' }
}
}}
])结合分区裁剪和列裁剪
将两种裁剪策略结合使用,可以获得最高性能:分区裁剪(路径中的时间或实体属性会跳过整个文件)以及列裁剪(提前使用 $project 跳过每个文件中不需要的 Parquet 列)。与针对未分区、未压缩数据集的朴素全扫描查询相比,两者结合可以将 I/O 减少 99% 以上。
// Combined: partition pruning + column pruning
db.events.aggregate([
// Partition pruning: only reads March 2025 S3 files
{ $match: { year: 2025, month: 3, eventType: 'purchase' } },
// Column pruning: only reads userId, amount columns from Parquet
{ $project: { userId: 1, amount: 1, _id: 0 } },
{ $group: { _id: '$userId', total: { $sum: '$amount' } } },
{ $sort: { total: -1 } },
{ $limit: 100 }
])监控分区裁剪效果
在 Atlas Data Federation 查询历史记录中,每个查询都会显示匹配的文件数量与实际读取的文件数量。如果匹配数 >> 读取数,说明分区裁剪效果良好。如果匹配数 ≈ 读取数,说明您的分区结构与查询模式不匹配,应该重新设计分区布局或添加更多分区属性。
// Check execution stats to verify pruning
db.events.explain().aggregate([
{ $match: { year: 2025, month: 3 } },
{ $group: { _id: '$eventType', count: { $sum: 1 } } }
])
// In the explain output, look for:
// 'partitionsProcessed': 31 (one per day in March)
// 'partitionsTotal': 365 (total days in the year)
// Effective pruning: 31/365 files scanned分区设计:实用检查清单
设计 S3 分区结构时:1) 确定查询最常用来筛选的字段——这些字段将成为分区属性。2) 将基数最高且最常用于筛选的字段放在路径层级的最顶层。3) 将每个文件的大小控制在 64–256 MB。4) 对于分析型工作负载,请使用 Parquet 格式,以同时受益于列裁剪。5) 对于时间序列数据,请加入基于日期的分区(年/月/日)。
// Example: well-designed partition hierarchy for event data
// Prioritises: region (high selectivity), then year, month, day
// Path: /events/{region string}/{year int}/{month int}/{day int}/
// Query: EU events in March 2025
// Reads ONLY: /events/EU/2025/3/
// Skips: all other regions and all other months/years
db.events.find({ region: 'EU', year: 2025, month: 3, eventType: 'purchase' })快速检查
测试您对本课中 MongoDB 和 NoSQL Databases 概念的理解。
课程回顾
在本课中,您学到了:分区属性会在 S3 路径中编码元数据,使查询引擎能够跳过不匹配的文件(分区裁剪);将 Parquet 中的分区裁剪与列裁剪结合使用,可以最大限度地减少 I/O;以及将文件大小控制在 64–256 MB,以平衡单文件 API 开销和裁剪粒度。接下来,我们将学习 Atlas Triggers,了解如何响应数据库事件。
用 AI 导师学习 JavaScript — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 30
- 课程
- 120
常见问题解答
「为查询性能划分 S3 数据」课时是免费的吗?
是的 — 「为查询性能划分 S3 数据」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 MongoDB Academy 课程的其余内容,请升级到 CoddyKit PRO。 MongoDB Academy 课程共包含 4 节课。
「为查询性能划分 S3 数据」这节课中我会学到什么?
您将为 S3 路径定义分区属性,使 Data Federation 能够剪除无关文件并快速提供分析查询结果。 你通过在浏览器中直接运行的动手代码来练习 MongoDB Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 MongoDB Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 MongoDB Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「为查询性能划分 S3 数据」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 MongoDB Academy 课中编写并运行代码吗?
能。每节 MongoDB Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。