集成 PureData System for Analytics 和 InfoSphere BigInsights 以执行电子邮件分析

将 BigInsights 的高级文本分析功能与您的仓库相结合

PureData™ System for Analytics 是 IBM 的核心仓库平台。本文将会解释如何将它与 IBM 企业就绪的 Hadoop 发行版 InfoSphere® BigInsights™ 相集成。我们将探讨集成概念,以及这种集成的主要用途,将 BigInsights 的高级文本分析功能与您的仓库相结合。我们将演示如何创建一个小型场景,使用从电子邮件提取的信息来充实员工数据,然后还会演示如何将此信息提取到 BigInsights 中,如何将提取的结果上传到 PureData for Analytics。最后我们还会展示如何从仓库访问存储在 BigInsights 中的数据,以简化下钻功能。

Benjamin Leonhardi, 软件工程师, IBM

Benjamin Leonhardi 是大数据/仓库合作伙伴支持团队的团队领导。在这之前,他是位于德国 Boeblingen 的 IBM 研发实验室的 InfoSphere Warehouse 软件工程师。他曾担任过数据挖掘、文本挖掘和挖掘报告解决方案开发人员。



Piotr Pruski, 技术支持专家, IBM

Piotr Pruski 是 IBM Information Management Business Partner Ecosystem 团队的一名大数据技术支持专家。他主要致力于帮助加速销售和合作伙伴成功,找到业务合作伙伴并吸引他们注意,使他们能够使用 IM 产品组合中的产品(即 InfoSphere BigInsights)。他以前研究过 DB2、IBM Smart Analytics System 5710,还在较短期间内研究过 IBM PureData System for Transactions。



Andre Albuquerque, 技术支持专家, IBM

Andre Albuquerque 是 IBM Information Management PureData Ecosystems 团队的大数据技术领导。他于 2009 年加入 IBM 加拿大实验室并研究各种 IBM 产品,比如 DB2 和 IBM 大数据平台。作为技术领导,他是 Big Data Fundamentals Bootcamp 的内容所有者。



2013 年 7 月 23 日

简介

企业集成是来自 IBM 的一种独特价值。客户拥有的一些大数据技术用例只能通过集成来实现。这需要将企业中的现有信息与企业外新的信息流相集成。如果不将结构化、非结构化以及半结构化数据一起分析,则无法实现想要的分析类型。这里将分析传统和非传统数据来源的价值,以及传统和非传统技术在结合使用时的价值提升。

在继续后面的介绍之前,请注意的是,整篇文章中会涵盖大量知识,并会省略一些我们认为很基本或很基础的信息。因此,我们假设您至少对 BigInsights、AQL、JAQL、PureData System for Analytics 和 Cognos® 有初步的理解。有关所有这些技术的更多信息,可在 参考资料 一节中找到。

PureData System for Analytics(以前称为 Netezza)

PureData System for Analytics(受 Netezza technology 技术支持)是一个用于严谨的分析的简单数据设备。它针对分析应用程序而简化和优化了数据服务的性能,使复杂算法的运行只需要几分钟,而不是几小时。您可能知道 PureData System for Analytics 就是 Netezza Appliances。该产品已重新命名,我们可交替使用这两个名称。

亮点:

  • 速度— 比传统自定义系统快 10-100 倍
  • 简单性— 快速、轻松的设置,具有简化的用户体验
  • 可伸缩性— PB 级用户数据容量
  • 智慧— 复杂算法的运行只需几分钟;内容丰富的集成分析库

InfoSphere BigInsights

InfoSphere BigInsights 帮助公司分析和发现隐藏在大量原始数据中的业务洞察,这些数据包括 Web 日志、单击流、新闻源、社交网络站点、传感器数据、电子邮件和即时消息等。BigInsights 为您现有的信息管理基础架构提供了补充,包含数据仓库和分析工具,扩展了您的分析功能,以包含更多种类和更大量快速变化的数据。

亮点:

  • 使公司能够快速探查大量原始数据,深入了解以前由于太大或太复杂而无法应对的操作挑战。
  • 处理传统技术常常忽略的各种不同的数据,包括结构化和半结构化格式的数据。这些数据可能很 “凌乱”,包含具有潜在的复杂关系的不同结构。
  • 能够在低成本的商用硬件上实现具有巨大的可伸缩性的企业级分析。
  • 增强并集成了流行的信息管理软件,包括数据仓库、关系 DBMS、数据流平台、商业智能工具,等等。

集成

下面的图表描绘了本文的数据仓库和 BigInsights 的基础视图。

表 1. 数据仓库与 BigInsights 的对比
数据仓库BigInsights
数据类型结构化数据任何类型的数据,无论是结构化还是非结构化
数据加载数据会在进入仓库之前进行整理和结构化,以最大化它的效用。原始数据可按原样存储,无需任何修改,保留了保真度和血统。
分析方法
  • 高价值、结构化的数据
  • 重复的操作和流程(比如交易、报告、BI 等)
  • 相对稳定的来源
  • 经过透彻理解的需求
  • 针对快速访问和分析而优化
  • 高度可变的数据和内容;一些可能具有较高价值
  • 迭代式、探索性分析(比如科学研究、行为建模)
  • 易变的来源
  • 专门的问题和不断变化的需求
  • 针对灵活性而优化
硬件强大的设备和优化的系统廉价的商用硬件

有效的大数据平台和方法需要与您 IT 基础架构的剩余部分相集成。您的架构中最不需要的就是另一种技术或数据筒仓。大数据技术应与现有数据仓库和分析技术协同工作,扩大它们的价值。

以下事实是本文剩余部分的基础,是我们希望和需要实现此集成的原因。

PureData System for Analytics 可处理数 TB 的结构化数据,但具有有限的非结构化功能。InfoSphere BigInsights 在处理结构化信息时具有限制,但它在非结构化分析上确实具有出众表现。结合两种系统的优势,我们能够:

  • 在 BigInsights 中分析大量非结构化数据,将结构化的结果写入 PureData System for Analytics 或根据需要使用 Netezza UDF 读取它们。
  • 使用标准的报告解决方案来访问 PureData System,使用非结构化信息充实结构化(比如 OLAP)报告。

用例描述

下图给出了我们将用作我们的集成场景的基础的用例。

图 1. BigInsights 与 PureData System for Analytics 集成的用例
该图显示了 BigInsights 与 PureData System for Analytics 集成的用例

该演示展示了 PureData System for Analytics 与 BigInsights 的集成,使用 Cognos 作为前端。员工记录存储在 PureData System for Analytics 中,电子邮件在 BigInsights 中存储和分析。一个 AQL 注释器将电子邮件评分为工作或私人。AQL 是一种注释式查询语言,一种类似于用于从文本提取结构化信息的 SQL 的编程语言。评分结果然后通过一个 JAQL Netezza 模块从 BigInsights 上传到 PureData System for Analytics。结果汇总并显示在一个 Cognos 报告中(员工和他们的私人电子邮件和工作电子邮件数量)。该报告还允许下钻到基本的电子邮件文本,然后会从 BigInsights 获取这些文本。这会使用 Netezza BigInsights 连接器功能来从 HDFS 读取信息。


文档分析

下面我们介绍如何创建一个简单的 AQL 注释器,并使用它从一组文档中提取结构化信息。我们首先将会介绍如何创建一个简单的 AQL 注释器,它可区分工作电子邮件与私人电子邮件。下一步是将电子邮件导入 BigInsights 中。然后我们使用一个 JAQL 脚本标注文档并将结果上传到 PureData System for Analytics 中。

这会封装我们已集成的 BigInsights 部分,但我们仍然需要创建一种从 Cognos 报告到基本电子邮件数据的下钻功能。为此,我们需要能够从 PureData System for Analytics 数据仓库访问 HDFS 文件系统。这是通过 InfoSphere BigInsights 随带的 Netezza UDF 扩展来实现的。我们将介绍安装过程并展示实现下钻功能的可能性。

我们提供了大量信息,所以该实现经过了显著简化。我们计划在未来的文章中提供上面描述的一些步骤的更多细节和替代方案。

AQL 注释器开发

我们将会简要介绍如何开发一个基于字典的 AQL 注释器,以区分工作电子邮件和私人电子邮件。例如,这个注释器可用于识别不需要归档的与工作无关的电子邮件,进而减少备份成本。由于受本文篇幅的限制,我们仅使用了 AQL 的小部分功能;我们的目的是让您知道可以怎么做。您的开发环境应类似于以下环境。

图 2. InfoSphere BigInsights Development Studio
该图显示了 InfoSphere BigInsights Development Studio

我们的注释器有两个字典,其中包含私人电子邮件和工作电子邮件的代表性词汇。在第二步中,我们将使用 AQL 统计两个类别的词汇的所有出现位置,最后为每封电子邮件计算一个数字或总分。将电子邮件识别为私人,意味着私人词汇比工作词汇更多,此时会得到一个负数,而工作词汇比私人词汇更多的工作电子邮件将得到一个正数。我们还将演示如何创建一个 AQL Java™ UDF,因为 AQL 没有自己的减法函数。不过,使用 Java 技术实现这些类型的功能没有什么意义。

当然,每个电子邮件集合可能具有不同的需求,所以我们使用一个培训类的电子邮件集合,它已手动划分为工作电子邮件和私人电子邮件;在这个受限的例子中,每个类别有大约有 10 封电子邮件。对于这些电子邮件,我们识别了词汇列表并创建了字典,我们假设您拥有 AQL 和开发环境的基础知识。您可以在 参考资料 一节中找到更多的细节和示例。

AQL 是一种模块语言,所以我们创建了一个包含两个模块的项目:Common 和 Email。Common 用于定义我们希望在其他项目中重用的 UDF。我们然后在主要的 Email 模块中使用它来提取电子邮件分数。

开发减法 UDF

要计算总分数,我们需要实现一个可将两个整数相减的 Java UDF。这可在您实现 AQL 的相同项目中实现,因为 BigInsights Eclipse 项目源自于 Java Eclipse 项目。以下是我们的 UDF 的代码:

package com.ibm.imte.taudfs;

public class Sub {
	public Integer sub(Integer i, Integer j) {
		return i - j;
	}
}

接下来,我们将创建一个名为 Common 的 AQL 模块,以实现此函数并导出它,以便在其他模块中使用它。以下是这个模块的源代码。我们还将上面的 Java 代码编译到一个 JAR 中,并将它放在同一个模块文件夹中。这个文件夹会自动放在 AQL 代码的类路径中。

module Common;

create function sub(i Integer ,  j Integer)
return Integer
external_name 'udfs.jar:com.ibm.imte.taudfs.Sub!sub'
language java 
deterministic
return null on null input;

export function sub;

因为我们导出了该函数,所以我们现在可在其他 AQL 模块中导入并使用该函数。一个最佳实践是将所有 UDF 放在一个独立的模块中。

在下一步中,我们将利用两个字典,它们分别包含指示私人电子邮件或工作电子邮件的词汇。请注意,我们并不打算实现 100% 的准确性。在某些情况下,私人邮件中会使用工作词汇,反之亦然,但我们会在每个文档的末尾计算一个总数。AQL 还提供了许多选项来过滤结果和提高注释器的准确性。但是,对于这个较小的例子,我们将利用一种非常基础的方法。以下是字典中的样例条目。

字典 private.dict

mom
sister
love
party
sister
happy easter
christmas
x-mas
...

字典 work.dict

business unit
invoice
sap
sybase
database
it system
solution area
kick-off
workshop
reporting solution
...

现在我们需要创建名为 Emails 的主要模块。在此模块的字典文件夹中,我们添加了如上所示的两个字典文件。现在,我们可在主要 AQL 文件中编写注释器。首先我们需要添加一个模块标识符,导入我们之前创建的 Common 模块。

module Emails;

import module Common;

现在我们需要导入私人字典并创建文档的一个 AQL 视图,提取该字典中的词汇在文档中出现的所有次数。有关 AQL 的更多信息,请参阅 参考资料

create dictionary PrivateDict
from file 'dictionaries/private.dict'
with language as 'en';

create view PrivateWords as
extract dictionary 'PrivateDict' 
	on R.text as match
from Document R;
output view PrivateWords;

类似地,我们需要对工作字典重复此步骤。

create dictionary WorkDict
from file 'dictionaries/work.dict'
with language as 'en';

create view WorkWords as
extract dictionary 'WorkDict' 
	on R.text as match
from Document R;
output view WorkWords;

我们对实际例子不感兴趣,只希望拥有单个数字,所以我们可统计每个词汇被找到的次数。AQL 与 SQL 非常相似,所以我们可在两个视图上简单地计算一个统计数字: WorkWordsPrivateWords

create view NumPrivateWords as 
select Count(P.match) as num from PrivateWords P;
output view NumPrivateWords;

create view NumWorkWords as 
select Count(W.match) as num from WorkWords W;
output view NumWorkWords;

现在我们已拥有每封电子邮件的私人词汇和工作词汇的发现次数。在下一步中,我们希望为电子邮件创建单个分数,所以我们从工作词汇发现次数中减去私人词汇发现次数。如果找到工作词汇的次数更多,该分数将大于 0。如果私人词汇更多,总分数将小于 0。要计算差,我们将使用前面定义的 AQL UDF。最后,我们输出视图 TotalScore,以便能够在 Java 和 JAQL 程序中使用它。此语句不同于导出语句,后者用于模块依赖关系。

create view TotalScore as
select Common.sub(w.num, p.num) as totalscore
from NumWorkWords w, NumPrivateWords p;

output view TotalScore;

我们现在已创建了简单的注释器,可在开发环境中使用提取计划视图对它进行测试。在结果中可以看到,我们的一个有效的注释器将所有 10 个示例工作电子邮件识别为工作,将所有私人电子邮件识别为私人。

图 3. 执行 AQL 的结果
该图显示了执行 AQL 的结果

最后,我们需要将生成的 AQL 注释器导出为 TAM 文件。使用 Export > BigInsights > Export Text Analytics Extractor,将为两个模块创建两个 TAM 文件。要将这些文件用于 JAQL,我们需要将它们复制到 BigInsights。出于本文的用途,我们假设它们位于文件夹 /home/biadmin/nz-demo/Annotator 中。在下一节中,我们将使用 JAQL 在 BigInsights 集群中存储的一组电子邮件消息上执行此注释器。

将数据导入 BigInsights

创建 AQL 注释器后,我们需要将电子邮件数据导入 BigInsights。可通过许多方式实现此目的。基本而言,我们需要确保数据存储在大型文件中并且是可以拆分的,以便它能够利用 Hadoop 架构。我们还需要保留将电子邮件 ID 与每个电子邮件相关联的能力。为了充分利用 Hadoop 中的并行架构,文件需要是可拆分的。这意味着文件加载器可将文件拆分为多个数据块。包含换行符的文件一定是可拆分的。一个压缩文件夹中的多个文件也可以进行拆分,只是需要使用了一种可拆分的存储格式,比如 lzo。

在我们的示例中,我们将使用包含两列的逗号分割文件:ID 和 TEXT。我们将电子邮件中的所有换行符替换为空格,因为这不会影响我们的注释器。如果换行符对您的分析至关重要,您可能需要以不同方式对这些字符进行转义。

在许多情形下,您将有一组文件,每个文件包含一个文本文档,比如电子邮件。在我们的例子中,我们使用了一段简单的 Perl 脚本来将这些文档转换为一个分割文件。JAQL 也可以处理文件集,但这不属于本文的讨论范围。我们的数据文件类似于以下形式:一个逗号分割文件,包含每个电子邮件的一行和两列:LABEL 和 TEXT。LABEL 是一个惟一电子邮件 ID,用于将电子邮件与一位员工和一个包含电子邮件内容的文本字段相关联。

1|Message-ID: <29394058.1075855815542.JavaMail@test> Date: Mon, 5 Jun...     
2|Message-ID: <9986382.1075855895922.JavaMail@test> Date: Wed, 16 Aug...
...

下面的 JAQL 命令将该文件加载到 HDFS 中:

read(del("file:///home/biadmin/nz-demo/combinedEmails.txt", 
	{schema: schema{label, text}, delimiter: "|", quoted: false})) 
-> write(del("hdfs:/tmp/emails.del", 
	{schema: schema{label, text}, delimiter: "|", quoted: false}));

我们决定将该文件以未压缩的分割文件形式保存在 HDFS 中。为了实现更高的性能和更低的存储空间占用,我们可在加载期间压缩它。为了实现最佳性能,我们还可以将该文件存储为序列文件。序列文件是原生的 JSON 文件,会提高加载速度,因为它们实际上会将文件存储为 JAQL 的内部数据表示形式。但是,序列文件不是人类可读的,所以我们不会在本演示中使用它。请注意指定文件模式和文件格式的语法。关于这些特性的完整文档,请参阅信息中心(参见 参考资料)。

使用 JAQL 分析文档

现在我们需要对结果进行注释。为此,我们需要导入 systemT 模块。这个 JAQL 模块包含对文本文档添加注释的函数:import systemT;

然后我们需要创建一个变量,指定如何在 HDFS 中读取该文件。因为我们不会使用 := 物化该命令,所以它只会在实际的注释步骤中执行:

emails = read(del("hdfs:/tmp/emails.del", 
{schema: schema{label, text}, delimiter: "|", quoted: false}));

现在,我们进行注释:

textemails = emails -> transform { label: $.label,  score: 
	systemT::annotateDocument( $, ["Common", "Emails"], 
			["file:///home/biadmin/nz-demo/Annotator"], 
			tokenizer="multilingual", 
			outputViews=["Emails.TotalScore"])};

JAQL 中的转换运算符允许我们计算 JSON 流中的新字段。我们指定两个字段:一个是标签(我们的电子邮件 ID),另一个字段由我们的 AQL 注释器计算。为此,我们使用 systemT::annotateDocument 函数。这会计算我们在 AQL 一节中描述的电子邮件分数并将它添加到标签上。我们结合使用该函数和以下函数:

  • $:第一个参数是我们希望注释的文档。在 JAQL 中,$ 指示当前的文档。annotateDocument 默认应使用两个字段:标签和文本。
  • ["Common", "Emails"]:第二个参数指定我们想要利用的 TAM 文件。您将它们指定为一个字符串数组,其中的字符串是 TAM 文件的名称。
  • ["file:///home/biadmin/nz-demo/Annotator"]:包含 TAM 文件的一个或多个目录,也可是一个压缩文件夹。
  • tokenizer="multilingual":这个参数指定,我们希望使用 LanguageWare 分词器 (tokenizer)。展示一个具有语法分析和多语言支持的强大的分词器。对于简单任务,空格分词器就足够用了,但在存在疑问时,应使用 LanguageWare。
  • outputViews=["Emails.TotalScore"]:最后一个参数指定我们希望将注释器中的哪些输出视图添加到 JSON 记录中。

现在我们已提取了电子邮件分数,并将它们添加到 JSON 记录中。结果如下所示:

[{ "label": "1",
  "score": {
  	  "Emails.TotalScore": [{"totalscore": -3}],
  	  "label": "8",
  	  "text": "Message-ID: <384643.10758531370..."
  }
},
...
{ "label": "9",
  "score": {
  	  "Emails.TotalScore": [{"totalscore": -4}],
  	  "label": "9",
  	  "text": "Message-ID: <8489243.10758620563..."
  }
}]

可以看到,结果以子数组形式添加到流中。这是必要的,因为 AQL 输出视图通常拥有多个结果。文本文件中可能有多个人、地址等。在我们的示例中,我们聚合一个总数,所以始终仅有一个最终结果。我们还希望能够将结果加载到一个 Netezza 数据库表中。为此,我们需要将数组扁平化(也就是说,我们希望将一个电子邮件 ID 列表和它们各自的分数放在一个扁平的表中)。这可在 JAQL 中使用 expand unroll 命令实现。它会将子数组上移一级,为子数组的每行创建一个父结果。

scoredemails =  textemails -> transform {label:$.label, 
				score: $.score."Emails.TotalScore".totalscore, } 
				-> expand unroll $.score 
				-> transform {label: $.label, score: $.score} ;

我们在这段代码中做了两件事。首先,我们展开了子数组并将它们合并到父数组中。然后使用转换更改了字段的名称,使它们与 Netezza 表中的名称对应。最后,我们需要将结果写入 HDFS 中,以便可以在以后获取它们,并将它们迁移到 Netezza 数据库中。为此,我们使用以下命令。

scoredemails -> write(del("hdfs:/tmp/emails/scoredemails.del", 
		{schema: schema{label, score}, 
		delimiter: "|", quoted: false}));

我们现在保存了一个扁平的分割文件,它包含两列(电子邮件 ID 和计算的分数),并将它保存到了 HDFS 中。该文件类似于以下形式:

1|-3
9|-4
10|10
11|19
12|16
13|9
14|16
...

我们现在可使用 jaqlshell -b analyzeemails.jaql 运行完整的 JAQL 脚本。也可将它打包为一个应用程序并通过 REST API 调度或调用它。

将结果上传到 PureData System for Analytics

接下来将介绍如何将上一节的结果上传到一个 Netezza 表。我们将利用 JAQL Netezza 连接器实现此目的。也可通过 Netezza UDF 拉取结果,下一节将介绍此方法。但在我们的演示中,分析部分是推送式的。出于操作原因,我们将分析和上传部分分开了。当然,也可在一个步骤中完成它们。

我们需要将 Netezza 连接器导入 JAQL 脚本中: import dbms::netezza;.

当然也可以使用标准的 DBMS 模块,但这不会得到最佳的性能。Netezza 模块利用外部表来执行加载和卸载,利用并行加载来实现最优的性能。您还需要将 Netezza JDBC 驱动程序 JAR 复制到 JAQL 文件夹 $JAQL_HOME/modules/dbms/netezza 或将该位置添加到类路径。

接下来,我们需要设置一个数据库连接。这需要 netezza::connect 函数及 JDBC 连接字符串和用户帐户属性。我们利用数据库 BIGIDEMO 作为我们的示例数据库。

db := netezza::connect( 
		url = 'jdbc:netezza://netezza_host:5480/BIGIDEMO', 
		properties = { user: "admin", password: "password"});

现在我们需要读取之间创建的文件。请注意,我们更改了模式名称。我们需要使用 Netezza 表中所用的相同列名称来加载它们,包括大小写区分性。

tblData = read(del("hdfs:/tmp/emails/scoredemails.del", 
			   {schema: schema{EMAIL_ID: long, WORK_PRIVATE: long}, 
			   	delimiter: "|", quoted: false}));

现在,我们需要准备 insert 语句。这类似于 JDBC。我们指定用于插入的数据库连接和表名: dataIn = netezza::prepareInsert( db, 'EMAIL_SCORE' );.

由于 PureData System for Analytics 的独特架构,无需指定提交次数或其他任何参数。JAQL 会自动在 4 次并行加载中加载数据,按数据分片 ID 来拆分数据。您可以指定拆分块数,它定义了数据要拆分为的部分数。如果加载的数据要用于进一步计算,这会很有用。如果没有定义拆分块数,那么这些数据会在单个线程中处理。对于我们的上传操作,我们不需要它们。

最后,我们可通过将电子邮件文件传输到插入语句中,以执行上传: tblData -> write( dataIn );.

我们已完成将数据上传到 PureData System for Analytics 中的操作。我们需要在后面几节中实现一个下钻函数。为此,我们需要摘录文本字段,使 PureData System for Analytics 可加载文本字段。PureData System for Analytics 支持最多 64,000 字节的正常字符字段和 16,000 字节的 unicode NCHAR 字段。为了摘录文本字段,我们使用了 substring 函数。

read(del("hdfs:/tmp/emails.del", 
	{schema: schema{label, text}, delimiter: "|", quoted: false}))
	->transform {ID: toNumber($.id), TEXT: substring($.text, 0, 15000)} 
	-> write(del("hdfs:/tmp/email_text.del", 
		{schema: schema{ID, TEXT}, 
		delimiter: "|",quoted:true}));

我们已将电子邮件分数上传到一个 Netezza 表中并准备好了用于下钻的电子邮件文件。现在可使用 jaqlshell -b uploadscoring.jaql 运行完整的 JAQL 脚本了。

Netezza UDF 安装

接下来我们将介绍如何安装 Netezza UDF。这些用户定义的函数允许从 PureData System for Analytics 访问 BigInsights 系统。这里提供了 3 个函数:

  • HDFS_READ:此函数允许您从原生 HDFS 文件系统读取文件。
  • HDFS_WRITE:此函数允许您将文件写入 HDFS。
  • JAQL_SUBMIT:此盘数在 BigInsights 上执行一个 JAQL 字符串。

您可在 BigInsights Web 控制台上的欢迎页面上找到 Netezza UDF 的安装程序。可以下载它们并将它们复制到 PureData System for Analytics 主机上。然后使用安装包的脚本文件夹中的 install.sh 脚本安装 Netezza 扩展。

这会将 UDF 解压到 Netezza 扩展文件夹中。我们仍然需要将它们部署到一个数据库中。在我们的示例中,创建了一个名为 BIGIDEMO 的数据库,它包含我们的示例表。要将 UDF 部署到该数据库中并指定连接的连接参数,可使用以下命令。它将部署 UDF 并存储 BigInsights 服务器的连接信息。您可以连接到两个不同的 BigInsights 服务器,将它们安装在不同的数据库中。

./nzbiuser --user admin --pw password --db bigidemo 
			--bilocation http://bi_host:8080 
			--biuser biadmin --bipw password

Netezza BigInsights UDF 现在已部署并可供使用。请注意,JAQL_SUBMIT 函数使用 BigInsights 中专门的 JAQL 应用程序,所以您需要部署此应用程序才能使用这个 UDF。

开发下钻函数

现在我们来看看如何开发一个下钻函数,它允许您在 Cognos 报告中选择一个特定员工,这将从 BigInsights 加载相应的电子邮件消息。使用该函数,我们将展示 BigInsights 和 PureData System for Analytics 在两个反向上的集成。我们已拥有前几节中从 BigInsights 上传到 PureData System for Analytics 的信息,现在将从 PureData System for Analytics 连接到 BigInsights。我们使用的函数将在下面给出。它利用 HDFS_READ 函数从 HDFS 读取电子邮件文本文件,指定加载参数,类似于一个正常的外部表加载定义。请注意,我们需要指定基础的部分文件,因为对于每个精减任务,JAQL 会将写入的文件拆分为多个部分文件。该操作对 JAQL 是透明的,但对 HDFS_READ 函数(一个 Java 表函数)不透明,这意味着它需要在查询的 FROM 子句中执行,而且您需要为它添加 TABLE WITH FINAL 关键字作为前缀。

SELECT 
EMPLOYEE.E_ID, 
EMPLOYEE_EMAIL.EMAIL_ID,
T.TEXT
from 
	BIGIDEMO..EMPLOYEE EMPLOYEE,
	BIGIDEMO..EMPLOYEE_EMAIL,
	table with final (hdfs_read('/tmp/email_text.del/part*', 
		'DELIMITER "|"', 'ID INT, TEXT NVARCHAR(15000)')) AS T
WHERE 
	EMPLOYEE.E_ID = EMPLOYEE_EMAIL.E_ID  AND EMPLOYEE_EMAIL.EMAIL_ID = T.ID

此查询的结果如下:

E_ID | EMAIL_ID | TEXT
5    |        3 | "Message-ID: <13093069.1075849668865 ... "
6    |        8 | "Message-ID: <384643.1075853137096.Ja... "
...

这会将所有电子邮件文本读入到 PureData System for Analytics 中,也可像利用其他任何表那样利用该语句。我们还添加了员工和电子邮件 ID,以便可以轻松过滤员工 ID。出于性能原因,您通常会为此添加一个 JAQL_SUBMIT 调用作为前缀,该前缀将过滤信息推送到 BigInsights 中。我们在本文中省略了此前缀,因为它将迫使我们创建一个存储过程,以首先执行 JAQL_SUBMIT,然后读取过滤的文档。我们可能还需要将员工 ID 添加到电子邮件文档中,或者将请求的电子邮件 ID 推送到 JAQL 字符串中。这不属于本文的讨论范围,所以我们只给出了以下代码:

CALL JAQL_SUBMIT('
	read(del("hdfs:/tmp/email_text.del", {schema: schema{id, text}}))
		-> filter $.id == "5" 
		-> write(del("hdfs:/tmp/single_employee_emails.del", 
				{schema: schema{id, text}}));
	');

我们现在已经完成所有准备工作,可以开始创建我们的 Cognos 报告了。


报告创建

我们会非常快地描述我们创建的演示报告。它也将包含我们的示例应用程序的数据库表。我们将首先展示数据模型层,然后展示创建的报告。它是一个直观的 Cognos 报告,所以我们仅介绍少量的细节。您可在 参考资料 一节中找到如何创建 Cognos 报告的更多信息。

数据模型

我们的数据模型由 6 个查询主体组成。4 个物理表、1 派生表用于简化报告的创建,还有一个基于查询的动态主体:

  • NATION:每条员工记录都有一个国家 ID,这是一个包含国家信息的查找表。
  • EMPLOYEE:一个包含员工记录的表。包含员工 ID、国家 ID、姓氏和名字。
  • EMPLOYEE_EMAIL:一个包含员工 ID 和电子邮件 ID 的表。所以我们可将电子邮件与一个特定的员工相匹配。
  • EMAIL_SCORE:这是用于存储我们的 JAQL 脚本中的电子邮件分数的表。它有两列:电子邮件 ID 和 work_private 分数。
  • EMAIL_SCORE_FILTERED:这个查询主体创建于 EMAIL_SCORE 之上,以简化报告的创建。
  • EMAIL_TEXT:这个查询主体允许我们使用上述函数下钻到给定员工的电子邮件文本。

我们基于同名的基础 Netezza 表,将前 4 个查询主体导入 Cognos 中。我们还需要在所有查询主体之间建立关系,以便在同一个报告查询中使用了来自多个查询主体的列时,Cognos 可在国家 ID、电子邮件 ID 或员工 ID 上正确地连接它们。

查询主体 EMAIL_SCORE_FILTERED 将每个电子邮件 ID 的工作分数简化为两个查询项(WORK_MAILSPRIVATE_MAILS),每个查询项为 0 或 1。它利用 CASE 语句检查 WORK_PRIVATE 分数是正数(表示工作列为 1,私人列为 0)还是负数(表示该工作查询项为 0,私人查询项为 1)。这使我们能够轻松地统计每个员工发送的私人和工作电子邮件数量。

查询主体 EMAIL_TEXT 利用我们在上一节中开发的下钻函数。它在一个原生 SQL 查询上创建。我们执行了一些细微的语法更改以适应 Cognos。当这个查询主体在 Cognos 报告中引用时,将执行基础查询,将电子邮件文本抓取到 PureData System for Analytics 中,然后抓取到 Cognos 中。完整的数据模型类似于下图。

图 4. 数据模型
该图显示了数据模型页面

组合各部分:Cognos 报告

我们的 Cognos 演示包含两个报告页面,它们通过下钻功能相连接。主要报告显示来自静态表 NATION、EMPLOYEE 和 EMAIL_SCORE 的列。它是一个员工表,包含个人信息(员工 ID、姓氏、名字、国家)和来自文本注释的信息(即发送了多少封私人和工作电子邮件)。我们还在员工 ID 字段上实现了一个下钻功能。如果选择了一个特定的员工 ID,则会使用该员工 ID 作为输入参数来调用第二个报告,以抓取此员工的电子邮件文本。

图 5. 主要报告页面
该图显示了主要报告页面

第二个报告页面包含特定员工的所有电子邮件的一个简单表。它显示从 BigInsights 专区的电子邮件 ID 和摘录的电子邮件文本。我们还显示了 work_private 分数。

图 6. 下钻报告页面
该图显示了下钻报告页面

结束语

我们演示了一种集成 PureData System for Analytics 与 BigInsights Hadoop 环境的方式。我们尝试演示了如何发挥每个环境的优势。PureData System for Analytics 用作运行 Cognos BI 报告的仓库和基础平台,BigInsights 用于存储和分析文本文件。在 BigInsights 中,我们使用强大的文本提取语言 AQL 来从非结构化的文本文件提取结构化信息。我们使用 JAQL 运行文本注释,并将结果上传到 PureData System for Analytics 中。最后,我们使用 Netezza UDF 实现了一个从 PureData System for Analytics 到 BigInsights 的下钻功能,展示了两个集成方向。我们通过一个电子邮件分析示例将所有这些步骤结合起来,在 BigInsights 中存储和分析电子邮件数据,在 PureData System for Analytics 中存储和分析结构化的员工数据。

我们涵盖了大量知识,所以我们无法非常详细地分析每个部分。在实际的生产解决方案中,AQL 要复杂得多。我们可使用 JAQL 以压缩和优化的方式存储数据,下钻也能够以一种可并行化的方式实现。无论如何,我们希望本文为您提供了一个不错的起点。


下载

描述名字大小
本文中使用的脚本和演示文件NZ-BigInsights-Article.zip96KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management, Cloud computing
ArticleID=938306
ArticleTitle=集成 PureData System for Analytics 和 InfoSphere BigInsights 以执行电子邮件分析
publish-date=07232013