引言(Introduction)
本章将帮助读者理解数据工程师用来表示与组织数据 的各类数据类型 与机制 。我们将以电商应用 为例,进一步讲解数据基础。同时,读者还将接触数据建模(data modeling)的概念以及数据的结构化程度(structuredness) 。
结构(Structure)
本章将涵盖以下主题:
- 电商应用示例
- 结构化数据与表格化表示
- 半结构化数据与 JSON 数据格式
- 非结构化数据与二进制数据格式
- 事务型数据与分析型数据
目标(Objectives)
在本章结束时,我们将能够理解如何把领域数据概念 映射到合适的数据类型 ,如何定义数据结构 ,以及如何将数据以应用所需的特定格式 进行表示。我们也将获得对事务型数据 与分析型数据的概念性理解。
电商应用示例(E-commerce application example)
考虑一个电商应用:某个卖家希望在其网站展示商品,多个用户会执行注册、登录、购买、退货、求助 等操作。现代应用中,每个动作往往包含多个步骤,需要前端界面 与后端应用服务器之间的复杂交互。
例如,在注册新用户 时,前端需要检查用户填写的邮箱地址 是否已被注册;底层数据系统需要生成一个唯一标识符 ,供各子系统唯一识别用户;随后生成用户档案 并存入后端数据库。数据工程师需要识别并设计底层数据系统 ,以确保功能正确、性能可靠且可扩展,从而带来良好的用户体验。在该用例分析中,我们已将用户档案(user profile)识别为一个实体。
再看购买商品这一更复杂的多步骤流程。完成购买所需的最小步骤列表如下:
- 在搜索框中搜索商品并获取列表;
- 选择要购买的商品及数量;
- 将商品加入购物车并检查库存;
- 接收收货地址并校验配送可达性;
- 处理支付、处理支付失败并最终确认订单;
- 发货。
每一步都需要读取 数据存储中的数据,并将该步的结果写回底层数据存储,供后续步骤继续处理。
例如,第 1 步需要根据搜索查询读取商品目录 ;第 3 步需要检查用户指定数量是否在库存 中可用,并将条目加入购物车 。这里,购物车是第 3 步的产出 ,会被第 5 步用于订单最终确认 。在该用例分析中,我们进一步识别出**商品库存(product inventory)与购物车(shopping cart)**等实体。
数据建模概览(Overview of data modeling)
聚焦上述示例,我们识别出一组数据对象(data objects) ,如用户档案 、商品目录 、商品库存 与购物车 。数据对象代表将被一个或多个数据处理器 创建、存储、修改与访问的逻辑数据单元 ,并可在处理器之间传递。识别并定义数据对象的过程称为数据建模(data modeling) 。
在识别出数据对象后,下一步是为其定义属性 及其所属位置/关联 。例如,用户档案 应包含:用户名(或 ID)、邮箱、手机号、邮寄地址等;商品目录应包含:商品 ID、商品名称、品牌、价格等。
表 8.1 展示了商品目录 中商品的属性 及其对应的数据类型:
属性名(Property name) | 数据类型(Data type) |
---|---|
标识符(id) | String |
名称(Name) | String |
品牌(Brand) | String |
价格(Price) | Integer |
表 8.1:商品目录属性及其数据类型
下面给出商品目录的一个示例定义:
javascript
class Product (
var id: String,
var name: String,
var brand: String,
var price: Int
)
在该示例中,目录中的每个商品有四个属性:前三个(id
、name
、brand
)用 String 表示,第四个(price
)用整数 表示。为属性分配正确的数据类型 非常重要,这样才能对其执行特定操作。例如,价格是数字,那么在结算时就可以按百分比打折。
数据建模取决于应用需求 以及底层数据存储技术。高层看,数据建模包括以下任务:
- 识别并定义数据对象;
- 识别数据对象之间的关系;
- 定义数据对象的存储与检索机制。
我们将在本章及后续章节讨论这些任务。
结构化数据与表格化表示(Structured data and tabular data representation)
以表格 表示结构化数据 并使用 SQL 检索的历史可以追溯到 20 世纪 70 年代,这也是关系型数据库管理系统(RDBMS)的核心能力。MySQL 是最流行的 RDBMS 之一,免费开源。MySQL 允许用户创建表、视图、索引来存取结构化数据。
以商品目录为例,可在 MySQL 中如下表示:
sql
CREATE TABLE product (
Id VARCHAR(64),
Name VARCHAR(255),
Brand VARCHAR(128),
Price INT
);
这里,VARCHAR(*)
表示字符串数据类型。
要可视化该 product
表中的数据,可参见表 8.2。该可视化强调两个概念:其一,列内所有条目的数据类型相同 ;其二,目录中的每个商品 在表的所有列 上都有合适的取值 。这两点共同构成数据所需的结构性 。若你的数据具备这些特征,就可以将其视为结构化数据 ,并选择使用传统 RDBMS进行存储与检索,如下表所示:
Id | Name | Brand | Price |
---|---|---|---|
"Id-0001" | "Smartphone A 1.1" | "Brand X" | 239 |
"Id-0002" | "Smartphone B 3.2" | "Brand Y" | 459 |
"Id-0003" | "Smartphone C 8.0" | "Brand Z" | 999 |
表 8.2:商品目录(Product catalog)
我们将在第 9 章《数据库与事务型数据》中对此进行详细讨论。
半结构化数据与 JSON 数据格式(Semi-structured data and JSON data format)
进入 21 世纪初,技术行业迎来范式转移:互联网更易获取,大量创新型 Web 应用涌现。社交媒体不仅让用户每日消费 互联网内容,也让他们持续产出数据------社交帖子、商品评价等日益普遍。
与此同时,大型企业为支持更高频 的业务创新,要求底层数据模型更频繁地变化 。结构化数据的局限在于强约束的模式(schema) ,难以适应需求的快速变更,于是半结构化数据开始流行。
继续以商品目录 为例:现代用户在购买前希望看到详尽的商品信息,但不同品类的属性差异很大。
- 智能手机:屏幕尺寸、内存、处理器等;
- 冰箱:容量、门数、除霜方式等。
电商网站往往售卖上百种 品类,并希望快速上新 。在此情境下,严格的模式约束会适得其反,半结构化模型更易快速适配。
JSON 数据格式(JSON data format)
最流行的半结构化数据格式之一是 JSON(JavaScript Object Notation) 。它是人类可读 的开放标准,广泛用于存储与传输数据,现代应用几乎都在使用。
仍以商品目录为例,若希望在目录中存储商品详情,可如下表示:
产品 1 -- 智能手机
json
{
"Id": "Id-0001",
"Name": "Smartphone A 1.1",
"Brand": "Brand X",
"Price": 239,
"Details": {
"Size": 5.4,
"Memory": "256 GB",
"Processor": "Proc-A"
}
}
产品 2 -- 冰箱
json
{
"Id": "Id-0105",
"Name": "Refrigerator M",
"Brand": "Brand K",
"Price": 1025,
"Details": {
"Capacity": 210,
"doors": 2,
"defrost": "auto"
}
}
在上述示例中,手机与冰箱都用 JSON 表示。JSON 以及基于 JSON 的半结构化系统允许我们无需强制模式就能存储并访问"手机的尺寸""冰箱的容量"等属性。
结构化 vs. 半结构化 数据模型(Structured vs. semi-structured data model)
如上所示,JSON 提供了现代应用所需的模式灵活性 。对比之下,结构化模型的模式更刚性 。继续以商品目录为例:假设网站最初仅售卖智能手机,则产品属性与类型会专为手机设计,如表 8.3 所示:
表 8.3:智能手机的商品目录模式(Product catalog schema for smartphones)
属性名(Property name) | 数据类型(Data type) |
---|---|
标识符(id) | String |
名称(Name) | String |
品牌(Brand) | String |
价格(Price) | Integer |
尺寸(Size) | 浮点数(Floating point number) |
内存(Memory) | String |
处理器(Processor) | String |
对应的 SQL 表可能为(7 列):
scss
CREATE TABLE product (
Id VARCHAR(64),
Name VARCHAR(255),
Brand VARCHAR(128),
Price INT,
Size FLOAT,
Memory VARCHAR(32),
Processor VARCHAR(64)
);
现在若要在目录中新增冰箱 品类(属性如容量、门数、除霜模式等),需要在不影响手机属性的前提下增加新列 ,可通过 ALTER TABLE
实现:
sql
ALTER TABLE Product
ADD COLUMN Capacity INT,
ADD COLUMN Doors INT,
ADD COLUMN Defrost VARCHAR(32);
而若使用 JSON 的半结构化模型 ,就无需 执行此类 ALTER TABLE
,因为 JSON 不强制模式。
除上述差异外,结构化(SQL)模型的模式刚性还带来其他限制:
- 列值不适用性与存储浪费 :同一张产品表中包含多品类数据时,并非所有列对所有品类都有效。例如,手机行中的
Defrost
、Doors
列无意义,造成存储空间低效 ;而 JSON 模型无需额外列,避免了额外存储。 - 变更成本高 :
ALTER TABLE
通常开销大 ,尤其当为新列指定默认值时,需要更新既有行,甚至可能在重建表时导致应用停机 。而 NoSQL 提供的 JSON 数据模型由于模式灵活 ,无需执行ALTER TABLE
。
选型建议(Choosing a data model)
选择契合需求的数据模型至关重要:
- 结构化模型 因强制模式而更健壮、错误更少;
- 半结构化模型 因模式灵活而更易适配变化。
二者在底层存储与检索软件 上也常不同;一旦系统围绕某种模型设计完成,迁移 通常耗时且昂贵 。因此,在设计大型数据系统时,应尽早做出正确的数据模型选择。
非结构化数据与二进制数据格式(Unstructured data and binary data format)
在智能手机普及的时代,人人都是"摄影师、摄像师"。每天都会产生海量非结构化数据 :文本、图像、视频等。许多现代场景需要低成本存储 并在需要时高效检索 这些数据。非结构化数据通常体量更大,通常存放于数据湖 (多以对象存储为后端),而不是传统数据库或数据仓库。文本、图片与视频在写入数据湖前,会被编码为二进制格式。
现代应用广泛利用 AI/ML 从非结构化数据中提取智能 。例如,电商网站上的商品评论(文本)可用于情感分析 ;聚合结果可帮助识别净负向评价 的商品并下架。又如,若用户想通过上传相似图片 来搜索商品,数据工程师可以使用向量数据库 与以图搜图管线来实现。关于这类业务用例所用的数据工程模式,将在第 16 章《领域特定模式》中学习。
事务型数据与分析型数据(Transactional and analytical data)
由日常业务操作 产生(或为其所需)的数据称为事务型数据 。事务型数据通常存放在事务型数据库 中,其对应的应用称为 OLTP(联机事务处理)应用。延续电商示例,用户注册、订单确认、记录支付失败等日常活动都依赖事务型数据。由于需要极低时延 的存取以保障用户体验,故此类数据使用事务数据库存储。对电商网站而言,事务数据读写的质量与速度直接决定用户交互体验。
与之相对,分析型数据 经过筛选与整备 ,用于分析、商业智能(BI)、战略决策等特定场景。以"下架净负评商品"为例,工程与业务协作可如下实施:
- 明确识别净负评所需的信息子集(例如只需商品 ID 与评论,无需完整商品详情)。
- 构建 ETL 管道,将筛选与整备后的数据存入分析型存储。
- 执行情感分析,并保存其输出结果。
- 运行分析查询,得到净负向反馈商品清单。
以上过程体现了事务型 与分析型 数据的差异。执行数据分析的用户应用称为 **OLAP(联机分析处理)**应用。第 2 章《数据工程模式、术语与技术栈》与第 3 章《批量摄取与处理》将进一步讨论与 OLTP/OLAP 相关的概念与模式。
下表(表 8.4)概括了事务型与分析型数据系统的差异(详细差异见第 10 章《数据仓库与数据分析》):
表 8.4:OLTP 与 OLAP 系统差异概览
维度 | OLTP 系统 | OLAP 系统 |
---|---|---|
数据来源 | 通常由面向用户的日常业务应用产生 | 通常从 OLTP 系统摄取作为后续分析输入 |
存储介质 | 多为事务型数据库 | 多为数据仓库 |
典型使用者 | 终端用户 | 数据分析师 |
时延需求 | 极低时延(直接影响用户体验) | 较高时延可接受(可降低软硬件成本) |
结语(Conclusion)
本章通过引入数据建模 ,奠定了数据工程基础;结合示例,理解了结构化、半结构化、非结构化 数据及其建模方式,以实现业务目标;并介绍了事务型数据 与分析型数据的概念。
下一章将讨论关系型与 NoSQL 数据库 、事务数据语义 ,以及 OLTP 应用常用的设计模式。