新闻中心
使用T-SQL进行数据分析
“了解你自己”是一句著名的古希腊格言。“了解您的数据”是当今的变体,它特别适用于dba和开发人员。无论您是继承数据库还是开发ETL流程,您都需要对正在处理的数据的结构和内容有相当精确的概念。在其他元素中,了解以下CPDA数据分析师选修课程中的内容确实会有所帮助:

每个表中每个列的数据类型;
列中保存的数据的真实数据类型(例如,VARCHAR列是否只包含INT数据);
(N)个VARCHAR字段的最大和最小长度
它还有助于对某些字段中包含的数据类型有一个公平的概念,这可以包括:
null的数目;
null的百分比;
零长度字段的数量;
零长度字段的百分比;
最后,了解字段中数据的分布是有用的,如果只是了解字段中包含的数据,而不必向下滚动数千条记录。诚然,这并不总是必要的,它的有用性将取决于所分析的数据。但是,由于这个练习的全部目的是了解数据,所以让我们假设,了解记录集中的每个元素表示字段的数量和百分比是有帮助的。
下一个问题可能是问为什么这些信息有用。我将始终保持适当的数据类型和数据长度使许多数据过程(从数据加载到查询)运行得更快。您将节省磁盘空间和备份时间。同样,基本的数据验证只能节省进一步分析明显错误的时间。此外,如果数据类型适当且准确,那么构建SSIS包就会非常容易。
什么时候应该配置数据?
显然,在开发周期的关键阶段,分析数据是很重要的。其中包括(除其他外):
创建数据导入过程时
如果您正在将本质上是其他人的数据加载到您的数据库中,那么您在很大程度上信任外部数据源。我不提倡将偏执作为一种生活方式,我强烈建议您在ETL过程的早期阶段验证外部数据的类型和内容。
假设您正在从外部RDBMS(不管是不是SQL Server)导入一个数百万行的表。您可能会使用第三方提供的数据字典为目标数据库定义字段类型。如果没有可用的数据字典,则可以使用SSIS来推断数据类型。在任何情况下,您都被迫信任第三方的元数据定义。你能确定这个定义是准确的吗?您确定开发人员能够按照精确的规格进行工作吗?他们是否很着急,所以设置了一个NVARCHAR(3000),同时告诉自己他们将在稍后的日期切换到NVARCHAR(25) ?然后,他们被其他更紧急的任务压得喘不过气来,直到临时修复成为永久性功能。现在你可能已经明白了。
你可能会问,为什么这很重要?速度是简单的答案。在使用SSIS时加载数据时,将尽可能多的行放入SSIS管道缓冲区中非常重要。数据类型越窄,每个缓冲区中加载的记录就越多,加载完成的速度也就越快。请记住:SSIS使用源元数据提供的最大可能数据长度来计算行宽,而不是每条记录中实际字段的宽度。
毫无疑问,使用正确的数据类型是基础。这不仅可以减少加载时间,还可以减少ETL周期后期的处理时间,并避免无意义的数据类型转换。
然而,一旦基本问题解决了,还有其他事情需要考虑。在列中包含的数据级别上,即使原始开发人员的能力毫无疑问,那么输入数据的人员的严格程度如何呢?您能确定一个不应该允许null的字段被设置为允许它们吗?并且您有一个令人不安的大百分比的null,这实际上使数据集无效?在这种情况下,最好早点知道,这样就可以在花费数小时开发一个注定要被丢弃的流程之前,向数据供应商反馈您的疑虑。
在另一个层面上,让我们假设您正在使用“提取、加载、转换”范例摄取数据。这意味着您将从数据源获取源数据并将其加载到宽字符列中,然后将数据转换为适当的数据类型。这意味着,首先要推导出适当的数据类型。独立于表元数据对源数据进行概要分析是最基本的,它可以让您为最终数据表中每个经过验证的最终列推导和定义最准确的数据类型。
当继承数据库时
前一节中给出的许多原因同样适用于继承的数据库。但是,在这里,合适的数据类型不是为了加速数据加载,而是为了减少处理时间和磁盘空间使用。是的,我知道,压缩现在在许多数据库中使用,磁盘空间很便宜,而且……
你可以说我是纯粹主义者,但我更喜欢适当的数据类型和宽度。在任何情况下,由于在您继承的数据库中使用的查询中的隐式转换,使用了多少不适当的查询计划?如果答案是“完全没有”,那么你就没有问题。但是对查询计划进行更详细的分析可能只会返回另一个答案:“哎呀……太多了”。
(相当)简单的数据分析脚本
那么,假设您接受分析数据是一个好主意的前提,下面是一种在SQL Server表上执行基本数据分析的简单方法。此脚本将在SQL Server 2008及以上版本上运行。该脚本被设计为分析单个表,它所做的是:
获取源表的核心元数据(列名、数据类型和长度);
定义一个临时表结构来保存所需的分析数据;
处理每个列以返回分析数据;
检测任何外键;
执行任何比率/百分比的计算;
为可能的变化添加任何建议;
执行基本域分析(达到最高长度阈值的列值的数量、列中不同元素的数量以及它所代表的总数的百分比)。
检测任何外键;
然后返回结果临时表的内容。
不可避免地,我上面建议的配置文件元数据只是配置文件数据范围的一个子集,它在分析源数据集时很有用。然而,与其试图让最佳成为优秀的敌人,我更倾向于建议一个脚本,该脚本将返回一组核心的概要元数据,我发现这是非常有用的起点。当然,然后您可以扩展脚本以添加您认为有用的任何其他元素。本文最后给出了一些我还没有时间编码的建议。
剧本注释
我使用INFORMATION_SCHEMA表来获取表和列元数据。如果您愿意,您可以使用系统视图。我添加了最小的错误捕获,加上一些基本的检查和平衡存在于脚本中,以确保:
表存在;
所选列存在;
脚本需要几个输入变量。这些都是:
表模式(这是必需的);
表名(这是必需的);
一个可选的以逗号分隔的列列表来分析(如果你让这个为空,那么所有的列都将被分析);
还有一系列预定义的标志(全部设置为true),它们是:
一个标志设置,用于指示是否需要文本列分析;
一个标志设置,用于指示是否需要数值列分析;
一个标志设置,表明您是否需要日期列概要;
一个标志设置,用于指示是否需要对大对象列类型进行列剖析;
一个标志设置,表明您是否希望应用域分析(这可能需要一些时间);
最后是
执行引用表或域分析的阈值;
处于可能异常的上或下阈值的记录百分比;
用来表示可能异常的列中null的百分比;
建议一列使用另一种数据类型时,允许与已定义数据类型的百分比差异;
请注意,脚本返回的关于潜在数据类型修改的建议仅仅是建议。你不必只看它们的表面价值。实际上,您应该在开发环境中彻底测试您建议对数据表进行的任何更改,并确保使用该数据的任何现有流程都能接受您所做的更改。不可避免地,您需要尽可能确信源数据不会发生变化,从而阻止使用建议的数据类型。
我必须警告您,这个脚本在非常宽的表上运行可能需要非常长的连接(我已经在400多个列的表上运行过它)。此外,不可避免地,分析数千万条记录表中的数据将花费时间。从只分析核心元素开始(通过将部分或所有可选标志设置为0)来获得对数据集的初步了解可能是有利的。然后,您可以在列的子集上运行进一步的概要文件,以分析似乎特别感兴趣的区域。例如,分析唯一ID的分布是没有意义的。
举报/反馈