首页文章详情

一文读懂数据建模的类型

王建峰2025-08-25 21:12
一文读懂数据建模的类型

如果您仍在直接提取数据: 从日志中 Select*, 并希望您的分析能够跟上,那么是时候重新考虑您的方法了。可扩展、可靠的数据工程——Airbnb、Netflix 和 Uber 等顶级科技公司所实践的那种——依赖的不仅仅是基本的模式。它始于数据建模技术,这些技术可以优化管道、加快查询速度,并使您的工程工作更顺畅、更易于维护。

数据建模是将原始、混乱的数据转换为可靠、可扩展系统的蓝图。它能让您设计出易于维护、查询速度快且值得信赖的数据管道!

在本文中,您将了解经验丰富的数据工程师用来理顺混乱流程的强大数据建模策略。这些模式对于构建强大的数据系统至关重要——无论是从零开始还是改进旧有工作流程。

1.主键

假设你经营着一家小型冰淇淋店,并保存了一份 顾客名单 。你可能有多个名叫 Alex 的顾客,但你不想在记录销售额时混淆他们。 因此,你给每个顾客分配了一个唯一的 ID 号

这里,Customer_Key主键——它是唯一标识此表中每一行的列。即使两个人的名字相同,他们的Customer_Key也总是不同的。

因此,在数据库中,

主键是表中的一列或多列的组合,用于唯一标识该表中的每一行

关键规则:

唯一性——没有两行可以具有相同的主键值。

非空— 主键必须始终有一个值(不能为空)。

稳定性——它不应该频繁改变。

2.外键

在我们的冰淇淋店中,我们已经在顾客名单中为每个顾客提供了一个唯一的 ID——他们的Customer_Key 。

现在,在我们记录每笔购买的销售记录中,我们不必每次都写“Alice Johnson”或“Bob Smith”。相反,我们只需写上他们的Customer_Key

销售表

并将客户详细信息存储在其他表中:

客户表

这里Customer_Key是将销售表链接到客户表的外键。

外键是一个表中与另一个表中的主键相匹配的列,从而在两者之间建立链接。

关键规则

匹配主键— 外键列中的每个值都必须存在于引用表的主键列中(除非允许 NULL)。

可以重复——与主键不同,相同的外键值可以出现在多行中(例如,同一个客户多次购买)。

可以为 NULL— 如果关系是可选的,则外键可以为空。

现在我们了解了主键外键,让我们更深入地了解它们是如何组合在一起的。

3.事实表

在我们的冰淇淋店里,每当有人买冰淇淋时,你就把它写在 记录 本上:

日期:2025–08–13

口味: 巧克力

数量:2勺

价格:6美元

这个笔记本基本上是你的事实表——它是你记录所有 可测量事件 (在本例中是销售额)的地方。

在数据库世界中,事实表存储定量的、可测量的数据——可以计数、求和或计算平均值的数据。

因此,如果我们根据冰淇淋店笔记本中的销售数据制作一个事实表,它可能看起来像这样:

代表销售额的事实表。

这里,Date_KeyProduct_KeyCustomer_Key是 外键 ,分别链接到日期、产品和客户表。QuantitySales_Amount是 事实 ——我们想要测量和分析的实际数字。

到目前为止,我们先画一个图,稍后在介绍维度细节、SCD 和模式类型时,我们可以继续扩展这个图:

Date_Key ------ Product_Key ------ Customer_Key .........(外键)\ |/\ | /Sales_Fact Table

4.维度表

我们有销售事实表,其中每一行使用外键记录一次销售:

|日期_Key |产品_Key |客户_Key |数量|销售_Amount || --------- | ------------ | ------------- | -------- | ------------- || 20250813 | 12| 301| 2| 6.00|

但这些关键数据只是数字而已。 要真正 理解 销售情况,我们需要知道:

代表什么日期20250813?

代表什么产品12?

谁是顾客301?

这就是维度表的作用所在——它们保存了所有的描述性细节。

维度是数据仓库中的表,用于存储有关业务实体的描述性属性(文本或分类信息)。

例如:客户维度表:

| Customer_Key(PK)|姓名|城市|忠诚度状态|| 301|爱丽丝·约翰逊 | 纽约|金牌|

| 302|鲍勃史密斯 |波士顿| 银牌|

Customer_Key是这里的主键

该表描述客户但不包含销售数字。

那么,我们再画一下图,里面有事实表,维度表,主键,外键。

冰淇淋店数据仓库——事实表和链接维度。

现在我们已经介绍了所有基础知识,让我们想象一下这样一种情况:我们想要跟踪客户及其最喜欢的口味。随着时间的推移,一些客户会改变他们喜欢的口味,我们需要决定如何在维度表中处理这些变化。所以,这就是 SCD 发挥作用的地方。

5.缓慢变化维度(SCD)

在数据仓库中,维度表通常包含随时间变化的属性。正确管理这些变化对于准确的报告和分析至关重要。根据维度属性变化的处理方式,SCD 可分为不同类型。最常见的类型是类型 1、类型 2 和类型 3

假设Bob 把他最喜欢的口味从 草莓 改为 薄荷。让我们看看每种 SCD 类型如何处理这个问题:

| 客户 ID | 姓名 | 最喜欢的口味 |

| 101| 爱丽丝 | 香草 || 102| 鲍勃 | 草莓 || 103| 查理 | 巧克力 |

a. SCD 类型 1 — 覆盖。

类型 1 只是用新值覆盖旧值。

没有保留任何历史记录,因此我们只能看到最新的信息。

当历史数据不重要时使用它。

因此,Bob 更改后的表格(类型 1):

SCD 类型 1:鲍勃以前最喜欢的口味“草莓”消失了。

b. SCD 类型 2 — 添加新行。

类型 2为每个更改添加一个新行。

这允许完整的历史跟踪

通常包括StartDate、EndDate或CurrentFlag来识别活动记录。

因此,Bob 更改后的表格(类型 2):

SCD 类型 2:现在我们知道了鲍勃以前的口味以及他喜欢它的时间段。

c. SCD 类型 3 — 添加新列。

类型 3通过为先前的值添加新列来保留有限的历史记录。

仅可跟踪一次先前的更改。

比类型 2 简单,但不保留完整的历史变化。

因此,Bob 更改后的表格(类型 3):

SCD 类型 3:我们可以看到 Bob 当前和之前的风格,但除此之外的旧历史则无法追踪。

6.数据仓库模式

我们已经介绍了如何管理不断变化的数据。假设我们的冰淇淋店想要分析销售情况、追踪顾客偏好并高效管理库存。为此,我们需要一种结构化的方法来组织数据,以便回答以下问题:

哪种口味最受欢迎?

哪些顾客购买巧克力最多?

本周我们的草莓冰淇淋库存够吗?

这就是模式数据建模发挥作用的地方。

在数据仓库的背景下, 模式就像定义数据组织方式的蓝图。它显示了事实表(记录交易或事件的位置)与维度表(描述实体,例如客户、产品或位置)之间的关系。

把它想象成一张地图:模式告诉你一切事物的位置它们是如何连接的,这样你就可以快速找到见解。

为什么是 Schemas ?????????????????????

现在我们有了基础,我们可以探索不同的模式类型——星型、雪花型和星系型——并看看我们的冰淇淋店如何使用每一种模式类型来回答业务问题

a. 星型模式。

想象一下,我们的冰淇淋店想要了解其销售情况。诸如“哪种口味的冰淇淋卖得最好?”或“Alice 这周买了多少个冰淇淋?”之类的问题应该能够快速回答。星型模式非常适合这类问题,因为它以一种简单且查询速度快的方式组织数据。

在星型模式中,销售数据位于我们称之为事实表的中心。该表记录了所有交易——谁买了什么、买了多少钱以及何时买的。围绕着这个事实表的是维度表,它们描述了每个实体的详细信息,例如客户或口味。我们可以把它想象成一颗星星

事实表是中心,维度表是向外辐射的点。

在我们的冰淇淋店示例中,“销售”事实表记录交易,而“客户”表“口味”表则提供描述性上 下文。例如,如果冰淇淋店想知道查理买了多少巧克力冰淇淋,只需将事实表与“客户”表和“口味”表连接起来即可。同样,为了了解哪种口味最受欢迎,冰淇淋店会从事实表中汇总数量,然后查找相应的口味名称。

冰淇淋店的星型模式。

星型模式设计原则。

在设计星型模式时,应遵循一组准则,以保持其高效、整洁且易于使用:

什么时候不使用星型模式????

规范化数据:扁平化会造成冗余和混乱的 ETL。

频繁更新:对于经常变化的数据来说并不理想。

多对多关系:难以清晰地表示。

大尺寸或宽尺寸:会减慢查询速度并浪费存储空间。

深层层次结构:扁平化会导致重复和复杂的计算。

复杂的临时查询:缺乏多表连接的灵活性。

我的看法是:当您的数据相对稳定、关系简单并且您希望快速查询时,请使用星型模式进行分析。

b.雪花模式。

请记住,我们的星型模式可以很好地组织销售,但仍然存在一个问题

IceTypeIDIceTypeNameCategoryName1简单蛋筒2简单杯3精美圣代 看到了吗? “简单”这个词在锥体和杯体上都重复出现。

如果我们想将“简单”重命名为“经典”,我们必须在所有地方进行更改。

随着我们商店的扩大和更多冰类型或类别的添加,这会变得混乱且容易出错

S nowflake 模式通过进一步分割维度解决了这个问题

我们创建一个类别表,而不是重复类别名称。

斌记录 类型现在只需使用 ID 即可指向正确的类别。

雪花模式----------------* 冰激凌 类型表 IceTypeID | IceTypeName | CategoryID-----------------------------------------1 | 蛋筒| 12 |杯 | 13 |圣代 | 2*类别表 CategoryID | CategoryName--------------------------------1 | 简单2 | 花式

雪花模式是一种组织数据的方法,以便将维度表分成更小的相关表以减少重复。

何时不使用雪花模式?

1.性能比存储更重要。

如果速度至关重要(例如实时仪表板),则这种额外的连接可能会降低速度。

2.维度小巧、简洁

拆分表只会增加复杂性,而没有太多好处

3. 你需要非常简单的报告

对于简单查询来说,星型模式通常更快、更容易理解。

c.星座图式。

星座模式,也称为事实星座模式,就像是星型模式的放大版本

它有多个共享一些维度表的事实表。

可以将其想象为几颗恒星共享同一颗行星——这就是为什么它被称为“星座”。星座”

想象一下你的冰店现在同时跟踪销售和库存

销售情况表→ 冰块销量、数量、价格

库存事实表→ 冰库存,供应商,数量

两个事实表都需要共享维度

顾客

冰型

日期

星座模式允许多个事实表共享维度,而不是重复维度。

何时使用星座模式???

对于同一业务,您有多个事实表。

事实表共享维度,因此可以避免重复。

您需要将多个业务流程一起进行分析

下面 ,我们将深入探讨 7 种高级数据建模技术——Airbnb、Netflix 和 Shopify 等公司也使用这些技术——展示它们如何轻松实现日常指标、简化复杂关系并帮助团队理清混乱的流程。这些技术是每位数据工程师在从头构建新系统或重构遗留 ETL系统时都应该掌握的。 下 文将涵盖以下内容:

这些先进的建模技术不仅仅是理论概念,它们构成了可扩展、高性能数据系统的基础。利用它们可以帮助您加快查询速度、优化存储、简化复杂关系,并构建能够应对未来挑战的管道。那就让我们开始吧!

1.累积表设计

假设你所在的公司每天追踪数百万个用户事件——登录、页面浏览、点击、购买等等。现在,产品团队的某个人想要一个显示每日活跃用户 (DAU) 的仪表盘。

如果直接在原始事件表上运行查询,它可能看起来像这样:

从事件中选择COUNT(DISTINCT user_id),其中event_date = '2025-08-01'; 听起来很简单,对吧?但问题在于:你的events表每天都有数百万行数据。在仪表板、报告或 API 上重复运行此查询会变得缓慢昂贵,有时甚至在高峰时段无法执行

这就是累积表发挥作用的地方。

累积表设计。

什么是累积表?

累积表是一种预先聚合的表。您无需每次都重新计算每日活跃用户 (DAU) 等指标,只需计算一次并存储结果即可。这样,当您或您的信息中心需要数据时,即可立即使用

想象一下提前准备一批饼干——你不用每次有人想吃的时候都从头开始烤。你只需从罐子里拿出一块现成的饼干即可。

示例:每日活跃用户

创建 DAU 累积表的方法如下:

创建 表daily_active_users ASSELECTevent_date,COUNT(DISTINCT user_id)AS daily_active_users,CURRENT_TIMESTAMP()AS last_updatedFROM eventsWHERE event_type ='login'GROUPBY event_date;

现在,每一行代表一天的数据以及当天的活跃用户总数。您还可以跟踪数据的最后更新时间。这样,除非发生任何变化,否则您无需修改历史数据。

为什么累积表很重要?

不妨将累积表视为您的性能提升器。您无需在每次有人请求报告时重新计算相同的数字,而是可以提前存储结果。这意味着:

累积表模式通常在现代数据仓库(如 Snowflake、BigQuery 和 Redshift)中实现,其中效率、可扩展性和成本优化发挥着至关重要的作用。

2.事实数据建模

事实表记录着您业务的真实情况。它们记录着发生的每件事:每笔订单、每笔付款、每次点击、每次配送。如果您想衡量增长、追踪客户行为或计算收入,您总会用到事实表。

但问题在于:这些表格不仅会增长,还会呈爆炸式增长。数十亿行的数据很常见,如果您不仔细设计它们,您的数据仓库就会变慢,查询成本会变得昂贵,您的数据团队也会被各种修复工作淹没。事实数据建模就是防止这种情况发生的办法。与其将其视为“存储数据”,不如将其视为“为清晰度和规模而设计”。

事实数据建模。

核心基本原理。

1. 清晰度——定义你的粒度。

粒度可以准确地告诉您事实表中的一行代表什么。如果它不清楚,那么您的所有计算都可能是错误的。

例子 :

Grain = “一份订单”:每行 = 一份订单。您可以轻松计算总收入或订单数量。

Grain = “一个订单商品”:每行代表订单中的一个商品。您可以分析哪些商品销量最高,但需要对每个商品进行加总才能得出每个订单的总收入。

关键规则:首先确定粒度。它为所有指标设置规则,并保持数据的一致性。

2. 稳定性——如何识别行

事实表中的每一行都需要一种可靠的方法来标识。如果您依赖于混乱的字段组合(例如user_id + timestamp),最终会遇到问题:重复、连接缓慢以及结果不一致。

更好的方法是使用单个稳定的键(通常称为代理键),例如order_id或session_id。这使得连接更快,查询更简单,并确保每个事件只被计数一次。

例子:

缺点:user_id = 101+ 2025-08-18 10:32:45→难以管理,容易复制。

好:order_id = 500123→ 该订单的单一、唯一标识符。

关键规则:干净的键可以使您的数据模型在扩展时保持稳定。

3.可扩展性——它将如何增长

事实表不仅会变大,还会变得 非常庞大 。对于拥有数百万用户或交易的企业来说,这些表的数据很快就会达到数十亿行。如果在设计时没有考虑到规模,查询速度就会变得非常慢,成本也会急剧上升。

关键在于确保查询仅扫描实际需要的数据。这时分区聚类等技术就派上用场了:

分区通常会按时间将表拆分成更小的部分。例如,如果您按销售额进行分区order_date,查询“上个月的销售额”时只会扫描该月的销售额,而不是整个历史记录。

聚类将具有相似值的行分组在一起,因此类似的过滤器WHERE order_type = 'electronics'可以更快地找到正确的数据。

通过这些策略,表可以从数百万行增长到数十亿行,而不会导致系统崩溃。

关键规则:可扩展的事实表会随着数据的增长而增长,同时保持查询的快速和经济实惠。

4. 背景——您需要哪些额外的细节

事实表本身只是原始数字。为了使这些数字有意义,您需要将它们与提供上下文的维度联系起来。

例如: 事实表可能显示:order_id = 123, product_id = 45, amount = $200。 就其本身而言,这只是一个数字。但通过与维度连接,你会发现它是:

一台200 美元的笔记本电脑(来自dim_product)

由伦敦的新客户购买(来自dim_customer)

现在数据可以回答更丰富的问题,例如“伦敦新客户购买电子产品带来了多少收入?”

关键规则:事实告诉你 发生了什么 ;维度告诉你 这意味着什么 。

精心设计的事实表可以将原始事件转化为您的企业可以信赖的可靠、快速且富有洞察力的数据。

3. 日期列表数据类型

在传统的数据模型中,跟踪多个日期的数据通常会创建多行记录,每行记录一天。这很快就会导致表格体积过大、查询速度变慢以及存储空间浪费。日期列表数据类型通过将实体的所有相关日期存储在一行内的单个数组或列表中来解决这个问题。

日期列表是区分普通数据模型和高性能数据模型的隐藏技巧之一。它不需要为每个日期创建单独的行,而是将多个日期存储在一行中的单个数组或列表中。这个概念很简单,但对性能和存储的影响却非常巨大。

工作原理:

您可以将用户活跃日期、预订持续时间或事件发生日期存储在单个数组字段中,而无需为每一天创建多行数据。例如,在酒店预订系统中:

{“booking_id” : “H1001” ,“guest_id” : “G45” ,“booked_dates” : [ “2025-08-01” , “2025-08-02” , “2025-08-03” ]}

这里,一行代表整个预订,但每个日期仍然可以查询。

┌──────────────────┐│ Dim_Date ││ (日期列表表)│└────────┬──────────┘│ date_key┌──────────┼────────────┐│ │┌──────▼──────┐ ┌──────▼──────┐│ Fact_Sales │ │ Fact_Orders│└────────────┘ └────────────┘

BigQuery 或 Snowflake 等现代仓库可以有效地查询这些数组。

理想用例:

跟踪不规则活动:无需为用户登录的每一天创建一行,而是将所有活动日期存储在一条记录中。

多日预订:每次预订可将酒店、航班或汽车租赁显示为一行。

灵活的事件安排:处理非连续或重复的事件,而无需重复每个日期的事件详细信息。

如何让它发挥作用

始终包含start_dateand end_date——这可以使筛选和分区更快。按重要字段(例如user_id或 )进行聚类或索引booking_id,以避免扫描大量数组。请记住,数组功能强大但并非万能:如果下游需要完全扁平的表,请仔细规划扁平化操作。

关键规则:

日期列表模式简化了多日期数据,减少了冗余,并使仓库保持快速且易于管理。

它在支持半结构化数据类型的现代云仓库(如 Snowflake、BigQuery 或 Redshift)中特别有用。

4.图形数据建模

假设你正在为一款流媒体应用设计一个推荐引擎。首先,你用一个关系模型构建它:用户、电影、类型、评分和好友关系等表。它运行良好,直到有人问起:

“给我看我朋友喜欢的电影,但仅限于动作类。”

突然之间,你需要将四五个连接操作串联起来——用户 → 好友 → 评分 → 电影 → 类型。查询变得繁重、缓慢且难以维护。随着数据集增长到数百万用户和电影,性能会急剧下降。

这就是图形数据建模改变游戏规则的地方。

你不用考虑行和连接,而是用节点和边来思考。用户是一个节点,电影是一个节点,类型也是节点。它们之间的关系——“FRIEND_OF”、“LIKES”、“BELONGS_TO”——就是边。有了这种结构,同样的推荐查询就变得简单了:从用户开始,沿着他们的FRIEND_OF边走,跳到他们朋友的电影LIKED,然后按BELONGS_TO动作过滤。

以前感觉像是在与 SQL 连接搏斗,现在感觉就像在跟随一连串的连接。

图形建模。

为什么这很重要?

图建模的优势在于它反映了数据在现实世界中的实际行为方式: 互联且动态 。每次出现新的关系类型时,您无需重新设计架构——只需添加一条新边即可。

关系数据库在关系简单的情况下运行良好——例如将客户与其订单关联,或将员工与其部门关联。但是,一旦要查看跨越多层级的连接,事情就会变得复杂且缓慢。

现在想象一下金融科技的场景。你需要抓住那些以微妙方式联系在一起的不法分子:

两个账户绑定同一张银行卡,

一组从同一 IP 登录的用户,

同一小组之间的推荐循环反复出现,

或使用同一设备拥有多个身份。

如果您尝试将其与标准连接结合在一起,您的查询将变成迷宫,并且性能会下降。

使用图模型,情况会更加清晰。每个用户、卡、IP 和设备都是一个节点。每个连接——“登录”、 “付款方式”、 “推荐”——都是一条边。您无需强迫数据库处理嵌套连接,只需遵循路径即可。需要查看可疑账户三步之内的所有用户?只需一次遍历,无需执行一堆混乱的 SQL 连接。

何时使用图形建模?

图表并非适用于所有数据集。如果您的数据主要是一对一或一对多关系(例如客户及其订单,或员工及其部门),那么关系模型通常更简单、更高效。

但当关系成为问题的核心时,图表才真正发挥作用。一些常见的用例包括:

欺诈检测——查找实体之间的隐藏联系。

社交网络——谁关注谁,朋友的朋友。

推荐系统——“购买 X 的人也购买了 Y。”

供应链——追踪跨多个供应商和零件的依赖关系。

IT 网络——跟踪系统和服务的连接方式。

5.桥接表

大多数情况下,事实表和维度表都能清晰地处理关系。但有时它们之间的关系并非一对多,而是多对多。这时,桥接表就派上用场了。

想一想:

一个学生可以选修多门课程,每门课程有多名学生

一部电影可以属于多个类型,每个类型又有多部电影

一名医生可以治疗多名患者,一名患者也可以看多名医生

如果尝试直接在事实表中建模,要么会无休止地重复数据,要么会失去丰富的关系。桥接表位于中间,映射所有有效组合,从而解决了这个问题。

桥接表的亮点:

教育系统——连接学生 ↔ 课程 ↔ 教师。

媒体目录——映射电影 ↔ 流派或歌曲 ↔ 播放列表。

医疗保健——管理医生 ↔ 患者 ↔ 治疗关系。

销售和营销——连接活动 ↔ 客户 ↔ 产品。

例子 :

上图显示了当学生可以选修多门课程并且课程可以有多名学生时桥接表如何提供帮助。

左边是学生

右边是课程

中间桥接表映射了哪个学生与哪门课程相关联。

例如:

学生 A 选修了数学历史课

学生 B 就读于历史专业

如果没有桥接,您要么会得到重复的行(混乱),要么会得到过于复杂的事实表(效率低下)。通过引入桥接,您可以将多对多关系分解为两个简洁的一对多关系:

学生 → 桥梁 → 课程

这使得模式保持清晰,使查询更可预测,并确保在聚合数据时不会重复计算。

关键规则:

当维度之间存在多对多关系时,请使用桥接表。它可以保持数据仓库的整洁,并确保分析结果的可靠性。

6.Data Vault建模

如果星型模式是为了快速分析,那么Data Vault 建模就是为了让数据仓库更加灵活且面向未来。它专为数据来自多个系统、随时间变化且需要可审计的环境而设计。

核心思想

Data Vault 不会将数据分成一个大表,而是将其分为三个构建块

1.中心→业务关键(不经常改变的事物)。

例如: 客户 ID 、 产品代码 、 订单 ID

2. 链接→枢纽之间的关系。

例如: 客户下订单 , 订单包含产品

3. 卫星→描述性细节(发生变化的属性)。

例如:客户的 电子邮件地址 、订单 状态 、产品 价格

因此,数据仓库就像乐高积木一样——集线器是锚点,链接是连接器,卫星添加细节。

示例:电子商务订单

假设您正在为一家网上商店建造一个仓库。

Hub_Customer:客户 ID(C123、C456……)

Hub_Order:订单 ID(O001、O002……)

Hub_Product:产品代码(P10、P20……)

Link_Order_Customer:将每个订单与下达该订单的客户联系起来。

Link_Order_Product:将每个订单与其包含的产品连接起来。

Sat_Customer:保存客户详细信息(姓名、电子邮件、注册日期)和历史记录。

Sat_Order:保存订单详细信息(状态、付款类型、发货日期)。

Sat_Product:保存产品详细信息(价格、类别、描述)。

以下是使用电子商务示例的数据库建模的流程图:

蓝色 = 中心(业务关键)

绿色 = 链接(关系)

红色 = 卫星(带有历史的描述性细节)

这样,您的读者就可以“看到”中心如何锚定模型、链接如何连接它们以及卫星如何用细节丰富它们。

为什么重要

可扩展:即使您每天摄取数十亿行数据也能正常工作。

灵活:无需重新设计模型即可轻松添加新来源或属性。

可审计:您始终知道 发生了什么变化、何时发生、从何地发生 。

它并非面向最终用户模型(星型/雪花型模型正是为此而设计的)。相反,Data Vault 是为这些模型提供数据的原始但结构化的基础

这篇 文章 就到这里。我写作是为了记录我的学习,也希望能帮助那些正在努力理解某个主题的人。如果你想让我讨论某个特定的主题,欢迎留言——我很乐意写你感兴趣的内容!

本文来自微信公众号“数据驱动智能”(ID:Data_0101),作者:晓晓,36氪经授权发布。