Mar 05 2010

关于招聘ERP顾问

Category: UncategorizedZeeno @ 08:44

我其实并不喜欢这活儿,看看事儿还可以,看人就差远了。但是有时候却不得不看,尤其是你的团队需要增加人手的时候。

在Oracle ERP实施领域,我们习惯将人员分为两种,一种是提供软件或者实施服务的所谓“乙方”,一种是上ERP项目的所谓“甲方”。相对而言,甲方的实施顾问更像是培训专员和客服,甲方的技术顾问更像是乙方致仕还乡的小官儿,只在小地儿谈论小道。在整体平均薪资上来讲,甲方要逊上一筹,但也稳定轻松了些许,不需要整年里出差漂流外乡。

在招聘人手时,往往面临几个困境:

  • 如果从乙方招聘,则薪资可能难以谈拢,但是水平有保证。当然,这也不是绝对的,我就见过很多例外。
  • 如果从甲方招聘,则薪资或可谈拢,但是水平多数都是高估的。由于环境的因素,很多人往往得过且过,所以工作多年,却并不见得水平渐长的,多数人干的活只值2000块。
  • 如果招聘新手,看着用功成本不高,但是培训也是件烦事儿,而且无法保证学成后跳往他方。

虽然自己就处在“甲方”,我却对甲方有点偏见。他们做开发却不懂数据库,设计功能却不了解系统功能和技术实现,全是些忽悠之辈。但是换个角度来讲,这却是在甲方的工作内容之一,尤其是在实业企业,技术是次要的,精通业务才是首要的,所以基础薄弱了些倒也无可厚非。

定位问题有时候是一个非常重要的问题。信息化绝对是一项与时俱进的工作,软件的升级换代非常迅速,如果因循固守,即便在企业里稳坐不动,但是对于个人而言,其知识也趋于淘汰之列。但是若过度跟进时势,却往往力有不逮,任何工作都是需要人力物力投入的,在一个注重投资回报率的时代里,企业不可能轻率地做出变更。这也是个人知识更新和企业信息化平稳升级的矛盾之一。基于这个考虑下,很多有心上进的人,便不乐意到这边来死守一方。

几年前注册orafans这个域名时,还有点念想,期望中国也能出现个地域性的Oracle ERP实施顾问的小圈子。后来渐渐发现,该圈子人员极少,而且从业人员往往半路出家专业功底不深,在现有的杭州地区从业人员来看,对技术兴趣缺乏,上进心极弱,这种大环境下,很难形成一种party似的氛围。

我觉得Oracle ERP从业人员至少应当具备以下几点:

  • 了解系统技术架构,最好了解数据库和应用基本知识。不要求能自己做二次开发、性能调优,但是至少要知道想要的功能能够通过哪些方式去实现。
  • 深入了解标准功能本身,不要一知半解。至少,要通读过所负责模块的官方文档。
  • 有持续跟进、学习的兴趣,保持升级的冲动。随着ERP的推进,不论从规模上看,还是从功能上看,肯定会出现平台扩展和升级的需求。

在这个行业,找一可聊之人,难哪!也只在此牢骚几句而已。


Feb 26 2010

关于Forms转换到APEX小记

Category: APEXZeeno @ 15:07

Oracle Forms是非常高效、健壮的开发工具,它的历史已经超过了20年,在今后几年里将会继续完善和支持下去。APEX已经具备了相当多的Web 2.0因素,它继承了Oracle Forms最大优势,那就是几乎可以用PL/SQL来完成所有的开发工作,对于企业内部应用,它无异成为了首选的平台。在这种趋势下,自APEX 3.2版本开始,就引入了Forms Converter,该工具用于将传统的Forms应用转换到APEX应用,对于一些Oracle Forms应用丰富、历史悠久的企业而言,它是相当吸引眼球的。

从FastForms到SQL*Forms,从CS架构到现在基于Web的WebForms,Oracle Forms的基础结构却变化不大,本质依旧是Java程序,程序逻辑的实现几乎完全基于SQL和PL/SQL。APEX则是非常纯粹的WEB应用开发平台,它需要的是PL/SQL、Java Script、CSS和最基础的HTML知识。对于开发人员而言,两者需要技术技能几乎相同。从Oracle Forms转移到APEX,对开发人员的技能培训几乎可以省略。Oracle Forms的几个核心组件:块(Block)、触发器(Trigger)、PL/SQL库、值列表(LOV)都可以交由Forms Converter完成转换。

转换器会生成XML格式的原数据文件,然后上传到APEX生成具体的Web应用。在这里,转换器的作用是“转换”,而不是“迁移”。两个平台在技术上是不同的,从而导致某些功能上的差异,比如Forms中的快捷键在目前的APEX中是不存在的,此外,Forms中某些java beans的应用也无法在APEX上实现。Oracle Forms和Oracle APEX各元素的差异主要如下表所示:

Oracle Forms Oracle APEX
Alerts 在应用层或页面上的验证逻辑中实现文本消息
Blocks 在APEX是区域(Region)
Canvases 在转换过程中被忽略
Editors HTML编辑器
Lists of Values 记录组在转换过程中将会被调整
Program Units 对应PL/SQL程序单元
Triggers APEX中没有触发器,不过页面查询过程有相应的机制实现逻辑,比如Processes

对于APEX 4.0版本,或许还有另外一些特殊的差异,比如Websheets,内置的图表引擎(这是非常酷的,可以做简单的BI),加强的Web Services功能等。在用户界面上,Oracle Forms响应迅速,而APEX则可以通过AJAX特效实现类似功能。

关于转换的具体操作,可以参考《Oracle® Application Express Application Migration Guide,这本书《Oracle Application Express Forms Converter》有更详细的介绍。


Feb 25 2010

不应因习惯而麻木

Category: UncategorizedZeeno @ 10:28

案例:ERP系统中项目数量非常多,在项目管理模块,有个WEB界面是用于调整任务信息的。克隆环境后,用户发现该功能的访问速度和正式环境有明显差异。经询问各方面人员(包括用户和实施顾问),都说没有做过任何特殊变动。

任何一名实施顾问,首要的经验就是要学会明确自己和普通用户的不同。一种业务,或者一个功能,绝对不能完全站在用户的立场来看待问题。如果用户说没有做过更改,那是从功能使用角度来讲的,作为系统和功能之间起到桥梁作用的ERP实施人员,还应当关注系统本身的变化。首先,克隆本身就是一种变化,比如硬件平台的变化、文件路径的变化、访问方式的变化,甚至系统参数(数据库或应用)也可能变化。任何一种变化,都可能导致用户体验的不同。一个新克隆的系统,第一次访问就发现速度变慢(或者变快),实施顾问应当事先就预料到各种可能的情况。从我的经验来看,没有做过变动的可能性非常小,那就通过一些简单的技术手段来找到这种变化。

先对该功能启用诊断后发现,有一段执行任务列表查询的SQL存在明显的性能问题。

克隆环境检查该SQL的执行计划:

SQL> set linesize 1000
SQL> set pagesize 1000
SQL> explain plan for SELECT *
  2    FROM (SELECT * FROM pa_task_progress_v) qrslt
  3   WHERE (task_manager_person_id = 126)
  4   ORDER BY project_name ASC,
  5            task_name    ASC
  6  ;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------
| Id  | Operation                                    |  Name                         | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------------------------------
……
|* 14 |               HASH JOIN                      |                               |     1 |   239 |  5274 |
|* 15 |                TABLE ACCESS BY INDEX ROWID   | PA_PROJ_ELEMENT_VERSIONS      |     2 |    86 |     3 |
|  16 |                 NESTED LOOPS                 |                               |   381 | 84201 |  5253 |
|* 17 |                  HASH JOIN                   |                               |   252 | 44856 |  4497 |
|* 18 |                   TABLE ACCESS BY INDEX ROWID| PA_PROJ_ELEMENTS              |   445 | 65860 |  4492 |
|* 19 |                    INDEX RANGE SCAN          | PA_PROJ_ELEMENTS_N1           | 81751 |       |   357 |
|* 20 |                   TABLE ACCESS FULL          | PA_TASK_TYPES                 |     9 |   270 |     4 |
|* 21 |                  INDEX RANGE SCAN            | PA_PROJ_ELEMENT_VERSIONS_N1   |     2 |       |     2 |
|* 22 |                TABLE ACCESS FULL             | PA_PROJ_ELEM_VER_STRUCTURE    |  1732 | 31176 |    20 |
|* 23 |               TABLE ACCESS BY INDEX ROWID    | PA_PROJ_ELEM_VER_SCHEDULE     |     1 |    34 |     2 |
|* 24 |                INDEX UNIQUE SCAN             | PA_PROJ_ELEM_VER_SCHEDULE_U2  |     1 |       |     1 |
……
----------------------------------------------------------------------------------------------------

再在正式环境中检查同一句SQL的执行计划:

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------
| Id  | Operation                                 |  Name                         | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------------------------------
……
|* 14 |               HASH JOIN                   |                               |     1 |   239 |  3793 |
|* 15 |                TABLE ACCESS BY INDEX ROWID| PA_PROJ_ELEMENT_VERSIONS      |     2 |    86 |     3 |
|  16 |                 NESTED LOOPS              |                               |   393 | 86853 |  3787 |
|* 17 |                  HASH JOIN                |                               |   253 | 45034 |  3028 |
|* 18 |                   TABLE ACCESS FULL       | PA_PROJ_ELEMENTS              |   446 | 66008 |  3025 |
|* 19 |                   TABLE ACCESS FULL       | PA_TASK_TYPES                 |     9 |   270 |     2 |
|* 20 |                  INDEX RANGE SCAN         | PA_PROJ_ELEMENT_VERSIONS_N1   |     2 |       |     2 |
|* 21 |                TABLE ACCESS FULL          | PA_PROJ_ELEM_VER_STRUCTURE    |  1883 | 33894 |     5 |
|* 22 |               TABLE ACCESS BY INDEX ROWID | PA_PROJ_ELEM_VER_SCHEDULE     |     1 |    35 |     2 |
|* 23 |                INDEX UNIQUE SCAN          | PA_PROJ_ELEM_VER_SCHEDULE_U2  |     1 |       |     1 |
……
----------------------------------------------------------------------------------------------------

从两者对比上看,可以发现正式环境中该SQL并没有用到PA_PROJ_ELEMENTS的索引,基本上可以确定两个环境同一个功能访问速度不同的原因。同样的语句,在克隆环境和正式环境中的执行计划不一样。两个环境分别重新收集统计信息后,依旧如此。

从用户角度看,问题出在系统方面;从实施顾问角度看,此类系统问题应当寻求技术人员尤其是DBA的帮助,为什么会出现这种差异。经过进一步的诊断,发现正式环境中 db_file_multiblock_read_count 参数被设置为100,而克隆环境中该参数被设置为8。在克隆环境中尝试调整该值,可以确定正是该参数导致了执行计划的不同。

这里不对db_file_multiblock_read_count做探讨,这应该交给专业的性能调优人员去分析。回到开始,我们在发现问题后询问各方人员,为什么都回答没有做任何特殊变动呢?这其实是个非常有趣的话题,我想,最大的问题还是出在“习惯”二字上面。做了几十上百次同样的操作,当某一天发现这种方式出现问题时,我们条件反射的把这种习惯性操作排除在外,而把问题原因归咎于某些未知的可能性上面。

一个有经验的实施人员,和一个没有经验的实施人员,其生产力差别可见一斑。


Feb 23 2010

Oracle UPK 和操作手册

Category: UncategorizedZeeno @ 14:17

一个很小的问题:Oracle ERP的操作手册怎么写?

我联想到一个很小的例子。过完年回来后,很多中餐馆都还没有营业,哪怕已经营业的餐馆里菜式也非常少,老板解释说厨师还没上班。再回头看肯德基、麦当劳之类的洋快餐,什么时候会说因为某人没来上班而不能吃某样食物?在每个营业员都可以做厨师的餐厅里,我们甚至没进去就可以先想好吃什么,而中餐馆里却不行,甚至很多时候,因为某厨师的离职而导致我们再也不去某家餐馆。

在很长的时间里,以及绝大多数的企业里的,操作手册就是一个文档,里面配以相关截图和简单的说明,花哨一点的可能会录制屏幕配以简单解说,而更规范的企业里或许直接以SOP来代替。基本上,如果没有规范的制定,每个人的操作手册肯定是五花八门,更多时候彼此都很难看懂对方写的手册,而没有经验的用户则更是看得云里雾里。

我心目中标准的操作手册应当包含以下几个要素:

  1. 具备明确的目标,该手册将让用户掌握什么功能的操作?
  2. 要直观,简洁。
  3. 对于关键点,应该有适当的说明。
  4. 导航要清晰、明确。

用户在看到操作手册之前,应当已经接受过初步培训。很多人拿着操作手册想了解背后的数据模型,拿着功能介绍想看操作细节,结果一个手册变成了大杂烩,什么都有,搞到最后则是连用户都不想看了。操作手册不是功能设计,更不是用户需求说明书,它只是让用户明白某个功能是如何运作的,要正常工作中应当如何规范操作。用户和实施顾问的角色是完全不同的,用户看的文档和实施顾问看的文档也完全不同。所以在操作手册中配以复杂的理论说明是非常应当避免的,我的看法是,连流程图都没有存在的必要。

一个规范的格式化的文档永远比个性化的文档更有价值。有时候,写手册也是一种艺术,哪怕已经制定了规范,不同的人写出的手册还是区别很大,比如用于习惯,比如符号表示,比如章节划分,这些细节上的区别往往很容易造成阅读上的障碍。

行业范围的标准和规范有时候比团队内部甚至企业内部的规范要有力的多,而且这种规范会更得人心。习惯也可以成为一种竞争力,团队协作经验有时候和个人能力一样重要。如果某一天因工作需要进入另一个团队,结果发现其管理方式迥异,转变的过程也会是非常痛苦的。在Oracle ERP领域,UPK的使用或许就是一种每个从业人员都应当掌握的技能。

Oracle UPK的上手非常容易,通过简单的设置,甚至只需要重复一遍操作过程就能形成一套非常棒的培训方案。它可以生成屏幕回放,对于每步操作都配以解释,有需要的话,可以按章节用HTML附上一段说明。若有需要,也可以直接发布成Word格式的操作手册,其质量丝毫不逊于以前手工截图的手册。也可以发布到网站上,并且和EBS系统进行菜单集成,直接从EBS跳转到操作手册。目前,Oracle EBS R12、PeopleSoft、JD Edwards等应用都已用UPK做培训文档,相信今后Oracle会有越来越多的产品的培训文档采用该种方式发布。

对于Oracle ERP操作手册编写,希望今后能有更多的企业采用UPK。这种工具和规范,对每一位从业人员都是有利无害的。

Oracle UPK 官方站点:http://www.oracle.com/applications/tutor/user-productivity-kit.html


Feb 04 2010

MPS Relief Worker

Category: Supply ChainZeeno @ 13:12

MPS计划的冲减主要通过MPS Relief Worker (MPS 冲减工作流程)进行,如有异常,则将导致MPS数量无法冲减,计划不准。作为Oracle ERP的核心功能之一,程序方面自然经过了诸多考验,然而在实际工作环境中,却依然会出现问题。这种问题,或许来自异常的数据量,也可能出在服务器性能上。MPS计划冲减说白了是一件很简单的事情,就是在需要冲减的环节,比如在下达离散任务或创建采购订单等特定事件发生时,系统会自动对比需求数量,并作相应冲减。在技术实现上是如下进行的:

  1. 指定事件(如创建采购订单)发生
  2. 触发器将数据插入接口 MRP_RELIEF_INTERFACE
  3. MPS 冲减工作流程处理接口数据

由于计划管理器的存在,可以保证数据被及时处理。计划管理器其中一个重要的步骤就是由MPS 冲减工作流程处理接口数据,实现冲减逻辑。但是有些时候,却发现系统总是出现很多的意外,比如可能找到这些错误:

mrupwj_update_wip_jobs 中出现 ORACLE 错误 1555

原因:由于 ORA-01555: snapshot too old: rollback segment number 2 with name "_SYSSMU2$" too small
ORA-06512: at "APPS.MRP_UPDATE_MRP_INFO_PK", line 284
ORA-06512: at line 1
, mrupwj_update_wip

mrupwj_update_wip_jobs 中出现 ORACLE 错误 1652

原因:由于 ORA-01652: unable to extend temp segment by 128 in tablespace TEMP
ORA-06512: at "APPS.MRP_UPDATE_MRP_INFO_PK", line 284
ORA-06512: at line 1
, mrupwj_update_wip_jobs 失败。

一方面,是因为DB配置的原因,另一方面,也是程序本身的问题。但是作为实施人员,这两块都无法改动,则只好对症下药,以其他方式来避免此类不是问题的问题了。

对于计划管理在冲减方面的逻辑,处理步骤上大致可以分为以下三步:

Step 1
取所有PROCESS_STATUS=2,并且REQUEST_ID为空的记录,将PROCESS_STATUS标记为3,同时将REQUEST_ID标记为处理的冲减流程请求ID。可以通过以下SQL观察哪些待处理数据:

SELECT *
  FROM mrp_relief_interface rel1
 WHERE inventory_item_id IN
       (SELECT inventory_item_id
          FROM mrp_relief_interface rel2
         WHERE rel2.request_id IS NULL
           AND rel2.error_message IS NULL
           AND rel2.relief_type = 2
           AND rel2.process_status = 2
           AND rownum <= 500
           AND inventory_item_id NOT IN
               (SELECT DISTINCT inventory_item_id
                  FROM mrp_relief_interface rel2
                 WHERE rel2.request_id IS NOT NULL
                   AND rel2.error_message IS NULL
                   AND rel2.relief_type = 2
                   AND rel2.process_status = 3))
   AND rel1.request_id IS NULL
   AND rel1.error_message IS NULL
   AND rel1.relief_type = 2
   AND rel1.process_status = 2;

REQUEST_ID先为计划管理器的并发请求ID,如果需要由MPS冲减工作流程来处理,则更新为新请求的ID。

Step 2
MPS 冲减工作流程在处理时,会根据配置文件预设值确定数量和方式。相关配置文件如下:

  1. MRP:Consume MPS (MRP:冲减 MPS)
    是否冲减MPS,设置为是
  2. MRP:Planning Manager Batch Size MRP:计划管理器批量
    每次处理接口数据的数量,建议值为500。最好不要超过1000
  3. MRP:Planning Manager Max Workers MRP:计划管理器最大工作进程数
    在设置批量大小时,每个MPS冲减流程只处理对应数量的记录,因而如果接口数据量较大,会同时出现多个并发。该配置文件就是用于限制最大并发数量的。

计划管理器也会处理PROCESS_STATUS=3的数据,但是这里的批数量只约束MPS冲减工作流程。

Step 3
如果第二步正常处理,则接口数据会被标志为PROCESS_STATUS=5。Planning Manager启动时,会检查接口数据,并启动Planning Manager Worker (once-a-day tasks),该请求会定期清理接口表中PROCESS_STATUS=5的数据。保留的时间范围由配置文件 MRP:Interface Table History Days 决定,默认是5天。

如果出现异常,则异常消息会记录在ERROR_MESSAGE,同时将PROCESS_STATUS标记为4。具体处理措施因事而异,如果需要重新处理,则必须先重置状态:

UPDATE mrp_relief_interface m
   SET process_status = 2,
       request_id     = NULL,
       error_message  = NULL
 WHERE m.relief_type = 2
   AND m.process_status = 4;

不要一次性更新太多数据,最好在配置文件 MRP:Planning Manager Batch Size 的数量范围内,分批次进行。在处理时,需要先停止计划管理器,修改完毕后再重新启动计划管理器。

下面的SQL可以检查接口表中各类数据的数量:

SELECT organization_id,
       SUM(decode(process_status, 1, 1, 0)) status1, --Do not process
       SUM(decode(process_status, 2, 1, 0)) status2, --Waiting to be Processed
       SUM(decode(process_status, 3, 1, 0)) status3, --In Process
       SUM(decode(process_status, 4, 1, 0)) status4, --Error
       SUM(decode(process_status, 5, 1, 0)) status5 --Successful completion
  FROM mrp_relief_interface
 GROUP BY organization_id;

需要留意的时,如果在功能逻辑范围内的错误,并不影响整个MPS冲减流程继续下去,但是如果是其他错误,如回滚段不足、快照陈旧等,会令MPS冲减工作流程挂起。在整个流程中,是根据并发请求状态来判断步骤是否完成的,因而可采取的措施是可以尝试手工修改并发请求状态,然后下一步继续执行。这种操作的后果就是冲减数量不正确。也可以先停止整个流程,待问题修正后重新启动MPS。

每次手工启动MPS计划流程时,都必须先执行MPS Relief Worker,就是为了保证计划数量的正确。而该程序正常执行的前提,就是接口中不应存在太多的数据。整个主计划的性能,由此可见一斑。


Jan 28 2010

EBS的后台执行方式

Category: E-Business SuiteZeeno @ 11:35

在应用中,应当避免执行一些长时间运行的操作,毕竟对于一个OLTP环境,快速响应才是重心。在某些情况下,可能无法使用批处理的方案,需要在用户界面做操作,但是某些特殊环节可以后台运行。这时候,在设计功能时就应当考虑异步处理机制,尤其是要用好批处理和后台处理等方式。

对于后台处理方式,EBS中大致有这么几种方式可选:

  1. 并发请求
    并发请求几乎可以实现任何耗时的运算,也是在EBS环境中常用的后台处理方式。比如很多地方都允许设置处理方式,如联机处理、后台处理等。根据系统性能和响应要求自行组合逻辑块。这种方式的优点是实现简单,管理方便,缺点是受限于并发管理器的配置。此外,大多数企业里的并发程序都运行在数据库服务器上,如果涉及到异构系统的数据传递需要考虑到安全方面的问题。
  2. 工作流 (Oracle Workflow)
    如果是逻辑判断比较清晰又比较复杂的话,这是不错的候选方案,实施顾问也可以非常清晰的看到各个流程走向。这个方式的优点是可以将运算逻辑模块化,缺点是偏长于逻辑判断,而不适用于大数据量运算。
  3. 业务事件 (Business Event)
    业务事件依托于Oracle Workflow,允许客户自行订阅并执行客户化代码。业务事件底层用到了AQ,可以将消息从数据库层传递到应用层。这也是我最欣赏的一块内容。EBS内置了很多标准的事件,比如付款、BOM更新、资产转移等。这种方式的优点是代码都在应用层执行,管理方式简单,缺点是标准的业务事件数量太少了。
  4. DBMS_JOB
    这其实算是一种非标准的方式,但是对于客户化应用比较合适。有时候,使用并发请求和业务事件都太过麻烦,但是通过JOB可以非常迅速的剥离执行逻辑,对用户而言,这可以算是比较标准的后台处理方式。这种方式的优点是简单方便,缺点是适用范围有限,适合在数据库层的运算。
  5. 管道 (PIPE)
    Oracle数据库管道技术在EBS系统中,我目前只发现MRP运算时有用到。它在应付多程序间通讯方面有优势,一个极端的应用是你可以在操作系统shell中实时看到某并发请求的运行情况。它的实现逻辑简单来讲,就是一个会话将消息发送的缓冲区,另一个会话从消息缓冲区读取消息。这种方式的优点是通讯方便,缺点是可能需要自行设计多会话间的消息封装机制,并且仅适用于小数据量传递。
  6. 高级队列(AQ)
    EBS中很多异步处理机制都利用了AQ,这相对而言太过于“底层”了,很少在二次开发领域有用到的。在大型的客户化应用中用的较多。

简单来看,对于后台处理方式就以上这么几种了。EBS R12中内置了SOA,可以通过外部平台进行运算,但是我不认为这是EBS系统范畴了。

个人比较推荐的是使用JOB,这在我的经验中是最简单有效的,不过前提是需要自行设计一套错误处理机制。如果涉及异构系统,我优先考虑业务事件。


Next Page »