我们公司使用 SQL Server 来托管所有应用程序数据已经有一段时间了。我们使用一种典型的设置,将数据从各种数据源加载到暂存区,然后为不同的数据集市提供其特定目的的数据(其中存储有定制的数据)。
然而,从我的角度来看,这会产生数据“孤岛”,它会重复大量数据,并且很难保持所有数据的同步。此外,随着解决方案数量的不断增长,“筒仓”数据集市的数量也成比例增长,因为需求总是略有不同,并且我们有明确的指示为每个解决方案使用单独的数据集市。
应用程序使用与数据集市的直接连接,然后使用和操作数据(根据需要)。
我最近对此进行了很多思考,目前正在进行一些其他举措来实现我们的后端现代化,因此我做了一些研究,我的想法是提出以下建议:
- 保持暂存区域不变(将不同来源的数据简单导入到一个数据集市)。每个源和相应的 SSIS 包都有一个架构来加载此数据。这一切都应该留下来。
- 为暂存区域内的每个解决方案创建一个架构。可以在此级别上管理访问权限,以确保应用程序使用者无法访问“导入架构”或其他架构,而只能访问属于他们有权访问的应用程序的架构。一旦实施第 5 点(API),应在连接到数据集市之前进行授权。
- 用新定义的模式中的物化(又名“索引”)视图替换当前加载数据集市的“筒仓”数据集市和相关 ETL 作业(SSIS 包)
- 将用于 CRUD 操作的任何表从以前的应用程序数据集市移至“暂存区域”数据集市中相应的新架构(需要重命名,因为它现在涵盖一个数据集市中的整个数据仓库)
- 实现一个简单的 API,该 API 具有对已定义视图的 GET 请求和对第 4 点中的表所需的 CRUD 操作的 POST 请求
当然,每个步骤对解决方案本身以及它们使用数据的位置都有很大的影响。此外,当然还需要大量的开发时间。但这暂时不是重点,这更像是一个普遍问题,这是否有意义或者如何在 SQL Server 上设置它。
我只是觉得我们围绕数据构建了太多内容,这也使得其他领域很难改进/加速后端流程。
非常感谢,祝本尼一切顺利
总的来说,我仍然有点困惑(其中一些只是因为我面前没有 ETL 堆栈)。但希望你能在这个答案中找到一些有意义的东西。
管理来自外部源的架构更改可能很乏味,具体取决于您构建堆栈的方式。这是我在处理外部数据源时通常构建事物的方式:
我将数据转移到我的服务器*上自己的数据库中,根据其来自的源数据库(如果已知)命名,否则根据源命名合理的名称。例如,我们称其为
SimpleSales
. 我完全按照来源提供的结构保留了结构。这使得稍后调试数据问题变得更容易(跟踪是否是数据源与我的规范化或转换的问题)。我在主数据库中创建了一个架构,其名称与步骤 1 中创建的数据库相匹配。例如:
CREATE SCHEMA SimpleSales;
在主数据库的新架构中,我创建引用源数据库中的本机对象的(常规)视图。通常这些视图与源对象是一对一的。我只为我最终要使用的对象创建视图。这是我规范化对象本身的名称及其列名称和数据类型的地方。
最后,如果我有特殊的业务逻辑,我需要在这些列的顶部合并,例如转换它们,我将在与正在运行的应用程序/域相关的更具体的模式(在我的主数据库中)的另一个视图中执行此操作消耗那个转变后的物体。例如,如果
SimpleSales.SalesOrders
是我的主数据库中的规范化视图,并且我需要为我的自动发票应用程序应用专用逻辑,我将拥有一个架构,例如AutoInvoice
我在其中创建专用视图,例如AutoInvoice.Customers
. 如果它是适用于大多数情况/许多不同应用程序的全局业务逻辑,那么我实际上使用名为 的模式Common
。我也用Common
统一来自不同外部系统的相关数据的架构。例如,如果我有两个不同的外部系统来维护销售数据(例如客户信息),那么我就会有一个视图,可以Commom.Customers
跨两个源提取不同的客户列表。(可选)如果我需要提高某些内容的特定性能,并且解决方案是使用索引视图,那么这可能必须在源数据库中发生。我通常会在源数据库中创建一个以主数据库命名的单一架构,以将这些自定义项放入其中。例如,在数据库中,
SimpleSales
我可能有一个PrimaryDatabase
架构,这就是对象的索引视图SimpleSales
所在的位置。视图(在不被滥用的情况下)是添加抽象层的好工具。当您使用视图作为消费对象时,除了重命名或删除依赖项的列之外,对根表的其他架构更改通常不会破坏您的消费堆栈。当发生重大架构更改时,只需更新主数据库中的根视图即可轻松应对更改。
另外,请记住索引视图的局限性。除了许多其他限制之外,无法使用外连接或自连接使得它们在适用于解决问题时更加适合。这就是为什么我在最初的数据结构中不默认使用它们。
对于更复杂的情况,还可以使用表值函数和存储过程,甚至可以像视图一样使用它们。但这是另一天的另一章了。
*至于如何将数据实际提取到源数据库中,实际上仅取决于您最熟悉的技术、数据需要更新的速率以及数据的大小。在我看来,SSIS 有点过时且复杂。在我的企业中,我很幸运能够在大多数情况下利用复制来进行实时数据同步。或者,如果数据不是非常大,并且不需要实时更新,则过程可以像纯 T-SQL 一样简单,将数据插入到新表中,重命名(或者删除,如果您不需要历史记录)现有表,最后将新表重命名为旧表名。不到 10 行代码就可以完成的事情。
我认为我从这个问题中得到的结论是,主要问题是不同“数据集市”中明显的数据重复。
在这一领域,尽可能使用通用表格生成完全集成的整体与为不同的报告开发保持合理程度的模块化之间可能存在紧张关系。
一切完全集成的结果是,对公共表的每一项提议的更改最终都会在可能的影响范围内变得巨大。
为了避免这种难以管理的工作,临时的附加装置和特殊的安排悄然出现,但不幸的是,这样做的方式组织得很差,有时本地化也很差(一次性功能或数据悄悄进入“公共”区域) ,而且命名方案也常常变得难以理解。
将来维护单独的报告模块也变得困难,因为需要偏离原始公共源的小调整可能需要从公共池中分离出许多东西,以便现在可以独立地改变处理。
但是,这种分离最终会在远离模块的原始分析和开发的地方及时完成,甚至可能不是同一个人完成的 - 不可避免地会导致更多的风险,对累积的测试产生更多的干扰,并需要更多的技能和经验。如果所有输入和处理都已经是独立的,那么开发人员的任务可能会小得多。
根据我的经验,维护工作量随着适度重复而增加的想法也是虚构的。
看起来,如果您发现在许多地方重复的代码中存在错误,那么修复它一定比它是由许多输出共享的单个代码更难。
实际上,复杂报告管道中的此类修复通常需要审查所有下游代码,以确定是否需要进行相应的调整。按照修复对每个模块的重要性的顺序,逐个模块地逐步进行修复,比在提交修复之前必须审查(或许还需要调整)报告系统中的所有内容要容易得多。
我的经验是,在报告系统中,为了明确的模块化和独立性,接受一些重复的数据更加可行和有弹性。