数据源与数据类型:结构化、半结构化、非结构化
做数据采集这么多年,我最大的感受就是:先搞清楚你要采什么,再想怎么采。很多人一上来就写爬虫、调接口,结果采回来的数据乱七八糟,根本用不了。说白了,数据源和数据类型就是整个采集工程的基石。这一块搞不明白,后面全是坑。
我个人习惯把数据源分成两大类来看:按数据结构分,和按数据来源分。这两条线交叉在一起,基本就能覆盖我们日常遇到的所有场景。
按数据结构分类
数据结构决定了你怎么存、怎么读、怎么处理。我把它分成三种:结构化、半结构化、非结构化。别小看这个分类,选错了存储和处理方式,性能差十倍都不止。
结构化数据
结构化数据,说白了就是行和列。每一行是一条记录,每一列是一个字段,字段类型固定。关系型数据库里的表就是最典型的例子。
核心特征:
- 模式(Schema)预先定义,字段名、类型、长度都固定
- 支持 ACID 事务,适合 OLTP 场景
- 查询效率高,SQL 一把梭
我在项目中遇到过最典型的场景:从 ERP 系统采集订单数据。订单表、客户表、商品表,全是结构化数据。字段清清楚楚,类型明明白白。这种数据采集起来最省心,直接 JDBC 连接,写个 SELECT 语句就搞定了。
| 特性 | 说明 | 举例 |
|---|---|---|
| 模式固定 | 字段名、类型、长度预先定义 | INT, VARCHAR, DATE |
| 存储方式 | 关系型数据库 | MySQL, PostgreSQL, Oracle |
| 采集方式 | JDBC/ODBC, SQL 查询 | SELECT * FROM orders |
| 典型场景 | 业务系统、财务数据、用户信息 | ERP, CRM, 订单系统 |
我的经验:结构化数据采集,一定要先拿到数据字典。没有数据字典,你连字段含义都搞不清楚,采回来也是垃圾。我曾经吃过这个亏,采了一堆字段名是 code1、code2 的数据,最后全废了。
半结构化数据
半结构化数据,有结构,但结构不固定。它自带描述信息(比如标签、属性),但同一类数据的结构可能不一样。JSON、XML、YAML 都是典型代表。
你想想看,一个 JSON 对象里,有的记录有 email 字段,有的没有,这在半结构化数据里太正常了。为什么?因为它的 Schema 是自描述的,数据本身带着元信息。
核心特征:
- 有结构但不强制统一,字段可以增减
- 数据自带描述信息(键值对、标签)
- 适合嵌套、层次化的数据表达
我记得有一次采集社交媒体数据,用户的个人资料就是典型的半结构化。有的人填了教育背景,有的人没填;有的人有多个手机号,有的人只有一个。用 JSON 存就特别灵活,用关系型表反而要搞一堆 NULL 字段。
// 半结构化数据示例 - 用户资料
{
"user_id": "1001",
"name": "张三",
"contacts": {
"email": "zhangsan@example.com",
"phone": ["13800138001", "13900139002"]
},
"education": {
"degree": "本科",
"school": "清华大学"
}
}
| 特性 | 说明 | 举例 |
|---|---|---|
| 模式灵活 | 字段可增可减,类型可变化 | JSON 对象、XML 元素 |
| 存储方式 | NoSQL 数据库、文档存储 | MongoDB, Elasticsearch |
| 采集方式 | API 调用、文件解析 | REST API, JSON 解析 |
| 典型场景 | 日志、社交媒体、IoT 设备数据 | 用户行为日志、传感器数据 |
注意:半结构化数据采集时,一定要处理字段缺失和类型不一致的问题。同一个字段,这条记录是字符串,下条记录可能是数组。我在做日志采集时就踩过这个坑,解析到一半程序崩了,就是因为没做类型校验。
非结构化数据
非结构化数据,就是没有固定结构的数据。文本、图片、音频、视频,都属于这一类。这类数据没有明确的字段定义,你没法用 SQL 直接查。
嗯,这里要注意:非结构化数据不是说它没有信息量,而是它的信息需要额外解析才能提取出来。比如一张图片,你看到的是一幅画,但计算机看到的是一堆像素点。
核心特征:
- 没有预定义的数据模型
- 数据量通常很大(MB 到 GB 级别)
- 需要专门的工具或算法才能提取信息
| 类型 | 存储方式 | 采集方式 | 典型场景 |
|---|---|---|---|
| 文本 | 文件系统、对象存储 | 文件读取、爬虫 | 新闻文章、PDF 文档 |
| 图片 | 对象存储、CDN | HTTP 下载、API | 商品图片、监控截图 |
| 音频 | 对象存储、流媒体 | 流式采集、文件上传 | 客服录音、语音指令 |
| 视频 | 对象存储、视频平台 | RTMP 推流、文件下载 | 监控视频、直播回放 |
我的建议:非结构化数据采集,优先考虑对象存储(比如 MinIO、AWS S3)。别往关系型数据库里塞,性能扛不住,成本也高。文件路径 + 元数据索引,才是正道。
按数据来源分类
数据来源决定了你怎么连接、怎么获取。我把它分成四类:数据库、API、文件、传感器。这四类基本覆盖了企业级数据采集的全部场景。
数据库
数据库是最传统、最稳定的数据源。关系型数据库(MySQL、PostgreSQL、Oracle)存结构化数据,NoSQL 数据库(MongoDB、Redis、Elasticsearch)存半结构化数据。
我个人习惯把数据库采集分成两种模式:
- 全量采集:一次性把整个表的数据拉过来。适合数据量小、变更不频繁的场景。
- 增量采集:只采集新增或变更的数据。适合大数据量、实时性要求高的场景。
增量采集的常用方案:
- 时间戳字段(update_time > last_pull_time)
- 自增 ID(id > max_id)
- Binlog 监听(MySQL 的 CDC 方案)
- 触发器 + 变更表
我曾经做过一个项目,每天要采集上亿条订单数据。全量采集根本跑不动,后来改成基于 update_time 的增量采集,配合分页查询,才把性能提上来。嗯,这里要注意:增量采集一定要处理好数据一致性,避免漏采或重复采。
API
API 是现代数据采集的主力军。RESTful API、GraphQL、gRPC,各有各的适用场景。我接触最多的还是 RESTful API,简单、通用、生态好。
API 采集有几个关键点:
- 认证方式:API Key、OAuth 2.0、JWT,搞清楚再动手
- 限流策略:QPS 限制、Token Bucket、退避重试
- 分页机制:Offset/Limit、Cursor、Page Token
- 错误处理:HTTP 状态码、重试策略、熔断机制
避坑指南:我曾经对接过一个第三方 API,文档上说返回 JSON,结果某个字段在数据为空时返回的是字符串 "null",不是 JSON 的 null。解析的时候直接报错。所以,API 采集一定要做字段级的数据校验,别信文档,信代码。
文件
文件数据源,说白了就是读文件。CSV、Excel、JSON、XML、Parquet、Avro,格式五花八门。文件采集通常用于离线批处理场景。
我总结了一个文件采集的优先级:
- 确定文件格式:文本还是二进制?定长还是分隔符?
- 确定存储位置:本地文件系统?FTP/SFTP?对象存储?
- 确定采集方式:全量读取?增量监听?定时扫描?
- 确定解析逻辑:编码问题、分隔符转义、空值处理
我的经验:文件采集最容易出问题的就是编码。UTF-8 和 GBK 混在一起,解析出来全是乱码。我现在的习惯是:所有文件采集统一转成 UTF-8,遇到编码不一致的,先做编码检测,再转换。
传感器
传感器数据源,是 IoT 时代的新宠。温度传感器、湿度传感器、GPS 定位、加速度计,每秒都在产生数据。这类数据的特点是:高频、实时、量大。
传感器数据采集的典型架构:
- 设备端:传感器采集原始数据,通过 MQTT/CoAP 协议上报
- 网关层:协议转换、数据聚合、边缘计算
- 平台层:消息队列(Kafka/RabbitMQ)缓冲,流处理引擎(Flink/Spark Streaming)处理
- 存储层:时序数据库(InfluxDB/TimescaleDB)存储
传感器数据采集的关键挑战:
- 数据质量:传感器可能故障,产生异常值或空值
- 网络不稳定:断连、延迟、丢包,需要本地缓存和重传机制
- 时序对齐:多个传感器的时间戳需要统一校准
我记得做过一个智慧农业的项目,田里部署了几百个温湿度传感器。刚开始没做数据质量校验,结果有个传感器坏了,连续报了三天 99°C 的高温,系统还傻乎乎地存进去了。后来加了阈值过滤和滑动窗口平滑,才把脏数据挡在外面。
知识体系总览
说了这么多,我画了一张图来总结本章的知识体系。你可以把它当作一个速查地图,以后遇到数据采集任务,先对照这张图,搞清楚数据源和数据类型,再动手。
小结
这一章的内容,说白了就是一句话:看清你的数据,再动手。结构化数据用关系型数据库,半结构化数据用 NoSQL 或文件,非结构化数据用对象存储。数据来源决定了你的采集方式:数据库用 JDBC/CDC,API 用 HTTP 请求,文件用读取解析,传感器用 MQTT/流处理。
我个人觉得,数据采集最忌讳的就是拿来主义——不管什么数据,先采回来再说。结果采了一堆垃圾数据,清洗成本比采集成本还高。所以,每次开始一个新项目,我都会花时间做数据源调研,搞清楚数据的结构、来源、质量,再设计采集方案。
最后分享一个习惯:我每次做完数据源调研,都会画一张类似上面那样的知识图谱。贴在墙上,团队里每个人都能看到。这样大家讨论方案的时候,不会因为对数据源的理解不一致而吵架。嗯,这招挺管用的。