投递文章投递文章 投稿指南投稿指南 RSS订阅RSS订阅

SQL Server 2005数据挖掘开发者指南

来源:Microsoft 发布时间:2008-01-06 收藏 投稿 字体:【

对于元数据发现(Discovery),ADO连接提供了一个OpenSchema函数(在OLE DB对话中打包了IDBSchemaRowset接口)。
OpenSchema 包含3个参数:
·         枚举,用来描述将要被发现的计划。
·         约束集,将被应用于发现操作的一系列约束。
·         全局唯一标识符(GUID),描述提供程序指定的计划。
我们尝试在MyCatalog 数据库上发现服务器端的挖掘模型。这不是数据挖掘模型计划(指定的提供程序计划)中预先计划好的枚举,所以第一个参数就是adSchemaProviderSpecific。第二个参数,约束集,包含用来查找模型(“MyCatalog”)的目录名。第三个参数包含Analysis Services OLE DB提供程序中,能识别挖掘模型计划的GUID的字符表。
6 Const DMSCHEMA_MINING_MODELS="{3add8a77-d8b9-11d2-8d2a-00e029154fde}"
7 Dim Restrictions()
8 Restrictions = Array("MyCatalog")
9 Dim rsSchema As ADODB.Recordset
10 Set rsSchema = Conn.OpenSchema(
adSchemaProviderSpecific,
Restrictions,
DMSCHEMA_MINING_MODELS)

数据挖掘的OLE DB规范包含分析服务的OLE DB提供程序支持的计划的完整定义,包括发现(Discovery)语句返回的列和约束。
OpenSchema返回一个ADODB.Recordset对象。Recordset对象封装了一个表型服务器响应。下面我们将看到如何遍历这个对象以及如何从中提取信息。这段代码的目的是枚举挖掘模型的名字。 像我们所知道的一样,在数据挖掘OLE DB里,挖掘模型计划中的每一行对应一种挖掘模型,并且包含一个“MODEL_NAME”列,列中存储挖掘模型的名字。
下面一段代码显示如何从Recordset 对象中查找指定的列,以及如何从这些列中提取信息。
11 ' 从(MODEL_NAME)中查找列
12 Dim iModelNameColumn As Integer
13 For iModelNameColumn = 0 To rsSchema.Fields.Count - 1
14    If rsSchema.Fields(iModelNameColumn).Name = "MODEL_NAME" Then
15      GoTo Found
16    End If
17 Next
18 Error (1)
19 Found:
20 ' 读取Recordset的返回值
21 rsSchema.MoveFirst
22 While Not rsSchema.EOF
23    Debug.Print rsSchema.Fields(iModelNameColumn).Value
24    rsSchema.MoveNext
25 Wend

如你所看到的一样,这段代码先遍历了Recordset 对象的所有字段。每个字段表示响应的一列。我们根据这些字段的索引MODEL_NAME进行查找。如果找到了这样的一列,就开始遍历它的行内容,否则就报错。
为了遍历行, Recordset指针先移到数据的开始位置。之后一行一行的读取行数据。对于每一行都读取和使用MODEL_NAME字段的值。
一些数据挖掘任务(如创建新元数据对象或训练已存在的对象)可以通过发送DDL语句到服务器来执行。让我们看看DDL语句是如何被OLE DB通过ADO来传输的。我们将使用与之前一样的连接对象,并介绍一个新的OLE DB对象的ADO包, ADODB.Command对象:
26 Dim Cmd As ADODB.Command
27 Set Cmd = New ADODB.Command
28 Cmd.ActiveConnection = Conn
29
30 Dim strProcessDDLStmt As String
31 strProcessDDLStmt = "" _
32 & "  </Process
xmlns=""http://schemas.microsoft.com/analysisservices/2003/engine"">" _
33 & "    <Type>ProcessStructure</Type>" _
34 & "    <Object>" _
35 & "      <DatabaseID>CheckInTestDB</DatabaseID>" _
36 & "      </Object>Structure1" _
37 & "    </Process>" _
38 & "  "
39
40 Cmd.CommandText = strProcessDDLStmt
41 Cmd.Execute
42

命令在一个活跃连接中执行。这个活跃的连接就是第28行中的内容。一般来说,这个命令包含着执行语句。这在CommandText 属性(第40行)中设置。当ADO为Analysis Services 2005打包OLE DB提供程序时,CommandText属性支持DMX语句和DDL语句(就像之前所展示的一样)。命令的执行被“执行(Execute)”方法初始化(第41行)。执行经常返回一个ADODB.Recordset 对象(可用于之前的发现(Discovery)代码段的表型服务器响应)。但是,处理操作是没有服务器响应的,它不返回成功或失败。如果出现了一个错误,ADO将报一个异常并停止正在运行的代码。因此,如果执行到了第42行,就说明执行成功了。
在之前的代码中,可以将CommandText 属性改为一个DDL语句,比如Alter、Create或者Drop;或改为一个DMX语句,如CREATE MINING MODEL或者INSERT INTO,它可以实现绝大多数挖掘任务。唯一一个需要附加补充的是查询挖掘模型。DMX查询与一般的无响应信息语句不同,因为:
·         它返回一个表型结果。
·         表型结果可能包含多级的表(嵌套表)。
·         DMX 支持参数。
我们可以从返回单级表的DMX查询开始看起,使用我们最开始使用的对象来对比(命令和连接):
43 Cmd.ActiveConnection = Conn
44 Cmd.CommandText = "SELECT NODE_CAPTION FROM DecisionTree1.CONTENT" _
45 &"where NODE_TYPE=2"
46
47 Dim rs As ADODB.Recordset
48 Set rs = Cmd.Execute()
   
49 rs.MoveFirst
50 While Not rs.EOF
51     Debug.Print rs.Fields(0).Value
52 Wend
53 rs.Close

如我们之前所提到的一样,DMX语句由CommandText属性来传输。与发现(Discovery)使用相同的方式来遍历Recordset。第44行用到的查询只返回一列,这里并不真正需要从recordset 字段来查找列;相反的,它应该由它的索引得到(第51行)第0字段的内容。也请注意第53行中对Recordset 的配置。当Recordset 是活跃的时候,命令对象不能执行之后的语句。
OLE DB规范也允许返回更加复杂的结果集,如表型列或者嵌套表。下面给出一个服务器响应是嵌套表的例子,我们将使用DMX语句来添加查询更复杂的第二列NODE_DISTRIBUTION。所以新的查询如下所示:
"SELECT NODE_CAPTION, NODE_DISTRIBUTION FROM DecisionTree1.CONTENT WHERE NODE_TYPE=2"

NODE_DISTRIBUTION 是一个典型的嵌套表例子。根据数据挖掘的OLE DB规范,模型中的NODE_DISTRIBUTION列包含当前行所在节点的属性值的分布。例如,在一棵预测头发颜色的决策树中,对每一个树节点,这一列都描述有多少实例是黑发,多少实例是金发,多少实例是灰发。
执行命令在新的一列中并不改变。实际上唯一需要改变的就是Recordset的遍历代码,需要进行适合表的新列的改变。在代码中可以很容易的从Recordset 作为字段值的属性返回一列的值。如果实例中的列是一个嵌套表,列值将产生一个新的Recordset,再遍历整个嵌套表。
所以,在51行以下应该执行如下的代码:
52     Debug.Assert( rs.Fields(1).Type = adChapter)
53     Dim nestedRS As ADODB.Recordset
54     Set nestedRS = rs.Fields(1)
55     nestedRS.MoveFirst
56     While Not nestedRS.EOF
57          Debug.Print nestedRS.Fields(0).Value
58     Wend
59     nestedRS.Close

第52行语句用来在将值写入嵌套Recordset前,确认列的类型是正确的。这行语句也可以用来判断制定的列是不是一个嵌套表。
应为拥有遍历嵌套表的能力,此时数据挖掘查询产生的任何返回值都可以在你的应用中被使用了。
DMX也支持查询中的参数。参数可以取代DMX查询中的任何值。例如,可以使用一个参数来代替上述查询语句中where子句里的NODE_TYPE 的值“2”。在数据挖掘应用中,也有少数参数非常有用的场景,比如生成一个单独的查询(关于单独查询的详细内容,请看“Adomd.NET”一节)。
想在DMX查询中将一个值变为一个参数,我们使用参数指示标志@来开始替换,使用“@唯一的参数名”。这样VBA代码片段中的第45行就可以变成:
45 &"where NODE_TYPE=@typeParam"

然后,在执行命令之前,我们应该插入这样的一段代码来确保能正确的使用新的参数。请注意,尽管实际数据可能与参数的值很不同,但是使用参数并不会改变服务器响应的格式。所以上述遍历Recordset 的代码可以并不改变。
46 Cmd.NamedParameters = True
47
48 Dim typeParameter As ADODB.Parameter
49 Set typeParameter = Cmd.CreateParameter()
50 typeParameter.Direction = adParamInput
51 typeParameter.Name = "typeParam"
52 typeParameter.Value = 2
53 typeParameter.Type = adInteger
54 typeParameter.Size = 4
55
56 Cmd.Parameters.Append typeParameter

在分析服务的OLE DB提供程序中使用参数时,如下的几步非常重要:
·         命令必须使NamedParameters可用(第46行)。分析服务的OLE DB提供程序只支持命名了的参数。
·         参数的名字必须符合查询中的相应参数,但是在这里不使用@前缀(第51行)。
·         可以只传输参数(第50行)。
·         参数的类型和大小必须声明(第53和54行)。
想对数据挖掘的OLE DB规则进行很好的理解,需要充分使用Microsoft Analysis Services 2005数据挖掘的特性。一旦设计好了数据挖掘查询,OLE DB就成为了一个可以执行它们、可以管理数据挖掘服务器的完整且具有通用性的API。关于在非托管C++或ADO.NET中C#使用OLE  DB 的代码,请看本文附录2中的代码片段。
Analysis Management Objects – AMO

如同名字所显示的一样,AMO是一个用来管理任务的API。它非常适用于描述元数据属性的细节信息。AMO是一种非常符合微软分析服务的数据定义语言(DDL)的对象模型,在AMO中描述元数据对象。它允许迭代元数据对象、创建新对象、修改已存在对象。在AMO对象模型中,用DDL描述的每个属性都可以被检查和修改。AMO也可以用来检查和修改服务器属性,包括注册/非注册型插件算法,或者可注册/不可注册数据挖掘算法。AMO在元数据的定义和发现,以及服务器对象的训练上都非常有用。但是,它并不支持执行查询语句。
在讨论细节信息之前,我们应该先来说明一下AMO是一个托管库。所以,它可以在由通用执行时间组件(CLR——Common Language Runtime)兼容的编程语言开发的应用程序中使用,如C#、托管执行的C++、或者Visual Basic .NET。要想使用AMO, 我们需要在客户机上安装SQL Server 2005连接组件。
在使用AMO的时候,我们首先应该在应用程序的开始处引用Microsoft.AnalysisServices.dll 库。之后,AMO对象模型就可以使用了。先来连接服务器:
Microsoft.AnalysisServices.Server server = new Server();
Server.Connect("localhost");

一旦连接成功,服务器端的元数据对象就可以被分级检查到:
Databases dbCollection = server.Databases;
foreach( Database db in dbCollection )
{
MiningStructures structCollection = db.MiningStructures;
foreach( MiningStructure struct in structCollection)
{
       Console.WriteLine( struct.Name );
}
}

如果想修改已存在的元数据对象,我们只需要修改它的属性。使用如下代码:
model.Algorithm="Microsoft_Decision_Trees".
then call "Update".
model.Update();

当Update被调用时,你所做的修改就将被提交到服务器,同时刷新本地的信息集。
在服务器上添加一个新的元数据、在各自的集合上创建新成员这两个方法,与修改功能也是非常相似的:
MiningStructure myStructure;
MiningModel myModel = myStructure.Models.Add();

之后填充对象的内容:
myModel.Name = "New Model"
myModel.Algorithm = "Microsoft_Clustering"

然后通过调用Update()来提交对服务器端所作的修改:
myModel.Update();

当操作未能成功执行完毕时,更新操作(Update)将返回一个异常。通常产生异常的情况是:
·         被更新的属性不完整或者不一致。
·         由于当前用户未能拥有足够的权限而引起的服务器不能更新对象。
当出现异常的时候,我们可以找到问题的所在并修复它。
AMO在处理Analysis Services 2005服务器端元数据上具有很强的功能,但是它并不支持之前所提到的数据挖掘任务中的部分任务。它不提供进度通知的功能,也不提供查询挖掘模型的功能(一般情况下,它不支持DMX语句的执行)。如果你的应用需要浏览和检查Analysis Services 2005服务器,使用AMO是最好的选择。但是,如果除此以外你还需要执行语句或者显示进度通知,AMO的功能就不够了。下一章将为大家介绍两种通用API,它们支持分析服务所公开的所有特性。
进度通知:使用跟踪对象
当在服务器端同时执行多个事件时,微软分析服务就会发送一系列通知。这些事件包括用户的登入登出、 执行请求的开始位置和结束位置、不同服务器对象正在执行的进度情况。在接收到通知以后,管理员就可以检查服务器在每一刻的状态。正在处理服务器对象的用户也可以从中了解正在执行的操作是什么,以及还需要执行多长时间。
这一节中,我们将讨论应用程序是如何从Microsoft Analysis Services 2005服务器来接收进度通知的。我们从如何发现服务器发出的通知看起。 之后,我们简短的介绍应用程序如何订阅它所感兴趣的服务器通知。最后,我们给出一个需要处理进度通知的应用程序的编程模型。
在进行深入的讨论之前,我们先来明确一下,SQL Server 2005使用一个客户端分析器(Profiler)来处理这些通知。使用这个分析器,用户可以真正根据自己的需要进行通知的选择,然后检查这些通知的具体内容。分析器应用程序也允许记录服务器通知,可以为了以后检查通知内容而先将它们保存下来。它也可以使用性能计数器(Performance Counter)将正在执行的不同的性能指示器的相关服务器通知整合起来。大多数应用程序并不需要在代码中执行服务器通知,这一节针对那些需要使用数据挖掘客户端高级用户接口的开发者来进行讲解。
服务器发出的每种通知都是一个表型行。这一行包含一些基本信息,例如通知的种类、时间戳、服务器进程ID、以及服务器的名称。其它列分别对应特定的事件,例如处理通知的Progress Total、起始时间、结束时间、在服务器上已经执行的时间。服务器发出的所有通知被存放在一张虚拟表中,它为每个事件保留一行,以及被任何服务器事件支持的所有列的集合。这意味着:如果列A只被一个指定事件支持,它将在这张虚拟表中所有的事件行中出现,但是不支持A的事件的列A字段是空值。说这张表是一张虚拟表,是因为它并不存放在内存中,也不能被直接访问到。当没有人去看服务器事件进展情况的时候,它被存放在一个只有管理员可以访问到的“flight-recorder”文件中,用来提供过去出现错误的原因相关的有价值的信息。
这张虚拟表中的列集可以用常规XMLA发现语句(Discovery)来发现。这个计划的XMLA名称是DISCOVER_TRACE_COLUMNS,它的GUID是{a07ccd18-8148-11d0-87bb-00c04fc33942}。这个计划中的每一行描述事件表中的一列,计划至少有一列,使用事件的XML格式进行描述。XML格式的描述如下所示:
<COLUMN>
  <ID>0</ID>
  <TYPE>1</TYPE>
  <NAME>EventClass</NAME>
  <DESCRIPTION>Event Class is used to categorize events.</DESCRIPTION>
  <FILTERABLE>false</FILTERABLE>
  <REPEATABLE>false</REPEATABLE>
  <REPEATEDBASE>false</REPEATEDBASE>
</COLUMN>
就这本白皮书来说,我们所感兴趣的属性有 ID、 名字(Name)和描述(Description)。
ID 是列的数值型标志符。像我们关于事件的讨论一样,一个事件通过定义ID来指定列。列的名字和描述对于客户端来说非常重要。基于这些属性,客户端应用程序可以判断哪些列是自己所感兴趣的列,哪些列是可以忽略的。ID为0的列是“服务器通知”这张虚拟表中最重要的列,因为它是用来定义事件类型的。Microsoft Analysis Services 2005发布的所有通知都包含此列。
发现服务器发布的事件是一个与发现列很相似的任务。使用的XMLA计划是 DISCOVER_TRACE_EVENT_CATEGORIES,它的GUID是 {a07ccd19-8148-11d0-87bb-00c04fc33942}。这个任务中的每一行描述一个服务器发布的事件类别,任务记录事件类别中的全部事件。当使用XML形式定义事件类别时,任务中的代码如下所示:
<EVENTCATEGORY>
  <NAME>Queries Events</NAME>
  <TYPE>0</TYPE>
  <DESCRITION>Collection of events for queries.</DESCRITION>
  <EVENTLIST>

<EVENT>
      <ID>9</ID>
      <NAME>Query Begin</NAME>
      <DESCRIPTION>Query begin.</DESCRIPTION>
      <EVENTCOLUMNLIST>
        <EVENTCOLUMN>
          <ID>0</ID>
        </EVENTCOLUMN>
        <EVENTCOLUMN>
          <ID>2<ID>
        </EVENTCOLUMN>
    ...
      </EVENTCOLUMNLIST>
    </EVENT>
    <EVENT>
      <ID>10</ID>
      <NAME>Query End</NAME>
      <DESCRIPTION>Query end.</DESCRIPTION>
      <EVENTCOLUMNLIST>
        <EVENTCOLUMN>
          <ID>0</ID>
        </EVENTCOLUMN>
        <EVENTCOLUMN>
          <ID>2</ID>
        </EVENTCOLUMN>
    ...
      </EVENTCOLUMNLIST>
    </EVENT>
....
  </EVENTLIST>
</EVENTCATEGORY>

所以,一个事件类别可以包含多个带不同ID的事件。如之前所说的一样,每个事件拥有它们自己的列,并且它们都包含提供事件类信息的列0。
另一个特殊的列是列1,事件子类(event subclass)。它被多个事件共享。事件子类这一列允许跟踪用户,例如,我们可以用它来区一个ProgressStart事件到底是来自于数据挖掘,还是OLAP维度处理。如果一个事件中出现了列1,这一列要比其它列的定义复杂一些。如下文所示:
<EVENTCOLUMN>
  <ID>1</ID>
  <EVENTCOLUMNSUBCLASSLIST>
    <EVENTCOLUMNSUBCLASS>
      <ID>1</ID>
      <NAME>Process</NAME>
    </EVENTCOLUMNSUBCLASS>
    <EVENTCOLUMNSUBCLASS>
      <ID>2</ID>
      <NAME>Merge</NAME>
    </EVENTCOLUMNSUBCLASS>
    ...
  </EVENTCOLUMNSUBCLASSLIST>
</EVENTCOLUMN>

这个更加复杂的定义描述了当前事件中列1可能出现的所有值的含义。
当一个应用程序决定了它感兴趣的事件或者事件列是哪些的时候,它可以订阅这些信息作为服务器通知。这个订阅功能在服务器创建跟踪对象的时候被创建。跟踪对象的功能与包含服务器通知的虚拟表的视图的功能相似。除此功能以外,跟踪对象存有服务器对象的所有属性。它可以被创建、修改、删除以及根据许可情况进行约束。一个跟踪声明会指定它感兴趣的事件(类似于关系型视图中的WHERE子句)以及事件将返回哪些列。定义跟踪的DDL可以包含更多的过滤条件,如“只返回那些列C是特定值的返回值”,但是这些过滤条件并不是本文要讨论的内容。这些高级选项可以从SQL Server 2005 在线文档中进行了解,在文档中有专门一节“跟踪要素(分析服务脚本语言)”。
让我们来考虑这样的一个应用程序,它用来训练挖掘模型,而且只订阅了如下进度报告事件:
·         Progress Report Begin (事件ID是5)
·         Progress Report Current (事件ID是7)
·         Progress Report End (事件ID是6)
·         Progress Report Error  (事件ID是8)
对每一个事件来说,感兴趣的列是:
·         列 0, EventClass。
·         列9, ProgressTotal,完成当前任务所需要执行的步骤数(此列仅在Progress Report Current事件可用)。
·         列10, IntegerData,数据挖掘进度通知中的属性,存储正在执行的任务的当前步骤(此列仅在Progress Report Current事件可用)。
·         列42, TextData,包含当前步骤的详细描述。
我们使用下面的DDL语句创建这个跟踪:
<Create
xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">
  <ObjectDefinition>
    <Trace>
      <ID>DemoTrace</ID>
      <Name>DemoTrace</Name>
      <Events>
        <Event>
          <EventID>5</EventID>
          <Columns>
            <ColumnID>0</ColumnID>
            <ColumnID>42</ColumnID>
          </Columns>
        </Event>
        <Event>
          <Event ID>6</Event ID>
          <Columns>
            <ColumnID>0</ColumnID>
            <ColumnID>42</ColumnID>
          </Columns>
        </Event>
        <Event>
          <EventID>7</EventID>
          <Columns>
            <ColumnID>0</ColumnID>
            <ColumnID>9</ColumnID>
            <ColumnID>10</ColumnID>
            <ColumnID>42</ColumnID>
          </Columns>
        </Event>
        <Event>
          <EventID>8</EventID>
          <Columns>
            <Columns>0</Columns>
            <Columns>42</Columns>
          </Columns>
        </Event>
      </Events>
    </Trace>
  </ObjectDefinition>
</Create>

最新5条评论 查看所有评论
评论内容:请自觉遵守互联网相关政策法规。
用户名: 密码: 匿名 注册
热门文章
随机推荐
About iTtang - 联系方法  - 专题列表 - 友情链接  -  高级搜索   -  帮助中心  -