确定数据类型和数据存储
可以通过多种不同方式对数据进行分类,这不仅取决于数据的结构化方式,还取决于数据的使用方式。 在此单元中,你将了解不同类型的数据的特征。
描述关系数据和非关系数据的特征
关系数据库可能是最容易理解的用于保存数据的模型。 表和列的简单结构使其一开始就易于使用,但死板的结构也可能会导致一些问题。 例如,在保存客户信息的数据库中,如何处理具有多个地址的客户? 是否添加列来保存每个地址的详细信息? 如果是这样,应该添加多少列? 如果允许保存三个地址,那么客户只有一个地址会发生什么情况? 在备用列中存储哪些内容? 如果突然有一个具有四个地址的客户,会发生什么情况呢? 同样,你要将哪些信息存储在地址中(街道名称、门牌号、城市、邮政编码)? 如果居所的名称不是数字,或者位于不使用邮政编码的位置,会发生什么情况?
可以通过使用规范化过程来解决这些问题。 通常,规范化过程的最终结果是将数据拆分为大量定义完善的窄表(窄表是包含很少列的表),其中具有从一个表到另一个表的引用,如下图所示。 但是,查询数据通常需要通过在运行时将数据重新联接在一起来重组多个表中的信息(如关系图中的线条所示)。 这些类型的查询的成本可能很高。
非关系数据库使你能够以更接近原始结构的格式存储数据。 例如,在文档数据库中,可以在单个文档中存储每个客户的详细信息,如上一个单元中的示例所示。 检索客户的详细信息(包括地址)时只需读取单个文档。 不过,使用文档数据库有一些缺点。 如果两个客户具有相同的地址,那么在关系数据库中,只需存储地址信息一次。 在下图中,Jay 和 Frances Adams 共有同一地址。
在文档数据库中,地址将在 Jay 和 Francis Adams 的文档中重复出现。 这种重复不仅会增加所需的存储,而且还会使维护变得更加复杂(如果地址发生变化,则必须在两个文档中进行修改)。
## Document for Jay Adams ##
{
"customerID": "1",
"name":
{
"firstname": "Jay",
"lastname": "Adams"
},
"address":
{
"number": "12",
"street": "Park Street",
"city": "Some City",
}
}
## Document for Frances Adams ##
{
"customerID": "4",
"name":
{
"firstname": "Francis",
"lastname": "Adams"
},
"address":
{
"number": "12",
"street": "Park Street",
"city": "Some City",
}
}
描述事务工作负荷
关系数据库和非关系数据库适用于不同的工作负荷。 关系数据库的主要用途是处理事务。
事务是原子级操作的序列。 这意味着序列中的所有操作都必须成功完成,如果出现问题,则在序列中迄今为止运行的所有操作都必须撤消。 银行转账是一个很好的示例;从一个帐户中扣除资金,并向另一个帐户存入等额资金。 如果在扣除资金之后系统发生故障,则必须在原始帐户中恢复相应额度(不得丢失)。 然后,可以尝试再次执行转账。 同样,也不能将相同的资金存入帐户两次。
每个数据库事务都有一个定义的起点,接着是数据库中数据的修改步骤。 最终,数据库要么提交这些更改,使效果永久保留,要么将更改回滚到可以重试该事务的起点。
事务数据库必须遵循 ACID(原子性、一致性、隔离性和持久性)属性,以确保数据库在处理事务时保持一致。
-
原子性确保将每个事务视为单个单位,要么完全成功要么完全失败。 如果构成事务的任何语句无法完成,整个事务都将失败,并且数据库保持不变。 原子系统必须保证每种情况下的原子性,包括电源故障、错误和崩溃。
-
一致性确保事务只能将数据库中的数据从一个有效状态转换为另一个有效状态。 一致的数据库绝不应丢失或以无法解释的方式创建数据。 在前面所述的银行转账示例中,如果将资金添加到某个帐户,则必须在某个地方有相应的资金扣除,或者如果资金是从外部收到的,则必须有描述资金来自何处的记录。 不能突然创建(或丢失)资金。
-
隔离性确保事务的并发执行使数据库处于与按顺序执行事务时相同的状态。 并发进程看不到处于不一致状态的数据(例如,已从一个帐户扣除了资金,但尚未存入到另一个帐户。)
-
持久性保证在提交事务后,即使发生系统故障(如停电或崩溃),它仍能保持已提交的状态。
处理事务工作负荷的数据库系统本质上是复杂的。 它们需要管理可能试图同时访问和修改相同数据的并发用户,在处理隔离事务的同时保持数据库的一致性和可恢复性。 许多系统通过在更新数据时对其应用锁来实现关系的一致性和隔离性。 锁会阻止另一个进程读取数据,直到解除锁。 仅当事务提交或回滚时,才会解除该锁。 大量锁定会导致性能不佳,而应用程序则会等待锁定解除。
许多组织都在使用分布式数据库。 分布式数据库是将数据存储在不同物理位置的数据库。 它可以保存在位于同一物理位置(例如,数据中心)的多台计算机中,也可以分散在互连计算机的网络上。 与非分布式数据库系统相比,对分布式数据库的任何数据更新都需要一段时间才能在多个位置生效。 如果在这种情况下需要事务一致性,则锁定可能会保留很长时间,尤其是数据库在关键时间点发生网络故障时。 为了应对此问题,许多分布式数据库管理系统放宽了事务的严格隔离要求并实施“最终一致性”。 在这种形式的一致性中,当应用程序写入数据时,每个更改都由一台服务器记录,然后以异步方式传播到分布式数据库系统中的其他服务器。 尽管此策略有助于最大程度地减少延迟,但它可能会导致数据不一致。 最终一致性非常适合于应用程序不需要任何顺序保证的情况。 示例包括社交媒体系统中的共享、赞或非线程评论的计数。
描述分析工作负荷
分析工作负荷通常是只读系统,可存储大量历史数据或业务指标,例如销售绩效和库存水平。 分析工作负荷用于数据分析和决策制定。 分析结果是通过将原始数据所显示的事实聚合为汇总信息、趋势和其他类型的“业务信息”生成的。
分析可以基于给定时间点的数据快照或一系列快照。 决策者通常不需要每个事务的所有详细信息。 他们需要更大的视野。
分析信息的示例是每月销售报表。 作为销售部门的主管,你可能无需查看发生的所有日常事务(事务信息),但你肯定需要每月销售报表来确定趋势并做出决策(分析信息)。
但是,事务信息是分析信息不可或缺的部分。 如果没有每日销售的完整记录,则无法编译有用的报表来确定趋势。 这就是为什么对事务信息进行高效处理是非常重要的。