【Oracle Database 12c New Feature】ILM – In-Database Archiving

本文介绍Oracle Database 12c中关于数据生命周期管理多个新特性中相对最简单的一个,数据库内归档(In-Database Archiving)。使用的测试表是上一篇介绍数据时间有效期管理中使用的TV表(包括表结构和测试数据),如果你还没有看过上一篇文章,可以先阅读【Oracle Database 12c New Feature】ILM – Temporal Validity

相比起数据时间有效期管理而言,数据库内归档非常简单,只有一个开关,对于一条数据,要不就是活跃的允许显示,要不就是归档掉不显示,这是由数据库管理员来人工操作的。

在设置数据库内归档之前,必须要在表级别启用该特性。如上一篇文章提到的,In-Database Archiving支持多租户架构,可以在PDB中使用。

SQL> alter table TV row archival;

Table altered.

Oracle仍然是使用隐藏列来实现这个功能的,在启用该特性以后,会自动在表上增加ORA_ARCHIVE_STATE字段,这是一个VARCHAR2(4000)的字段。

SQL> select COLUMN_NAME,DATA_TYPE,HIDDEN_COLUMN FROM USER_TAB_COLS WHERE TABLE_NAME='TV';

COLUMN_NAME          DATA_TYPE            HID
-------------------- -------------------- ---
ORA_ARCHIVE_STATE    VARCHAR2             YES
SYS_NC00005$         RAW                  YES
VALID_TIME_END       DATE                 YES
VALID_TIME_START     DATE                 YES
INSERT_TIME          DATE                 NO
VALID_TIME           NUMBER               YES

6 rows selected.

先检查一下TV表中的数据分布,一共有9个不同的时间段,前面5个都只有1条记录,后面4个则有大量测试记录。

SQL> select INSERT_TIME,count(*) from TV group by INSERT_TIME order by 1;

INSERT_TIME         COUNT(*)
----------------- ----------
20130811 09:04:30          1
20130811 09:08:27          1
20130811 09:22:30          1
20130811 09:39:40          1
20130811 09:45:22          1
20130811 09:50:44      19368
20130811 09:50:46      19368
20130811 09:50:47      19368
20130811 09:50:48      19368

9 rows selected.

尝试将所有20130811 09:50之后的记录全部设置为归档模式。直接使用UPDATE语句将ORA_ARCHIVE_STATE字段更新为任意非0的字符,0表示该记录是活跃的,任何非0字符都表示该记录被归档。

SQL> UPDATE TV SET ORA_ARCHIVE_STATE = '20' WHERE INSERT_TIME>to_date('20130811 09:50','YYYYMMDD HH24:MI');

77472 rows updated.

再次执行相同的查询语句,可以看到只存在活跃的5条记录了。

SQL> select INSERT_TIME,count(*) from TV group by INSERT_TIME order by 1;

INSERT_TIME         COUNT(*)
----------------- ----------
20130811 09:04:30          1
20130811 09:08:27          1
20130811 09:22:30          1
20130811 09:39:40          1
20130811 09:45:22          1

5 rows selected.

可以在会话级别设置即使是记录被归档,也仍然显示出来。

SQL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL;

Session altered.

SQL> select INSERT_TIME,count(*) from TV group by INSERT_TIME order by 1;

INSERT_TIME         COUNT(*)
----------------- ----------
20130811 09:04:30          1
20130811 09:08:27          1
20130811 09:22:30          1
20130811 09:39:40          1
20130811 09:45:22          1
20130811 09:50:44      19368
20130811 09:50:46      19368
20130811 09:50:47      19368
20130811 09:50:48      19368

9 rows selected.

检查ORA_ARCHIVE_STATE值,可以看到所有活跃数据的ORA_ARCHIVE_STATE字段值均为0,这也是在表级别启用数据库内归档以后的默认值。

SQL> select ORA_ARCHIVE_STATE,INSERT_TIME,count(*) from TV group by ORA_ARCHIVE_STATE,INSERT_TIME order by 2;

ORA_ARCHIVE_STATE    INSERT_TIME         COUNT(*)
-------------------- ----------------- ----------
0                    20130811 09:04:30          1
0                    20130811 09:08:27          1
0                    20130811 09:22:30          1
0                    20130811 09:39:40          1
0                    20130811 09:45:22          1
20                   20130811 09:50:44      19368
20                   20130811 09:50:46      19368
20                   20130811 09:50:47      19368
20                   20130811 09:50:48      19368

9 rows selected.

将其中的一些记录的ORA_ARCHIVE_STATE字段更新为另外的非0字符。

SQL> update TV set ORA_ARCHIVE_STATE='ARCHIVING' where INSERT_TIME='20130811 09:50:48';

19368 rows updated.

SQL> select ORA_ARCHIVE_STATE,INSERT_TIME,count(*) from TV group by ORA_ARCHIVE_STATE,INSERT_TIME order by 2;

ORA_ARCHIVE_STATE    INSERT_TIME         COUNT(*)
-------------------- ----------------- ----------
0                    20130811 09:04:30          1
0                    20130811 09:08:27          1
0                    20130811 09:22:30          1
0                    20130811 09:39:40          1
0                    20130811 09:45:22          1
20                   20130811 09:50:44      19368
20                   20130811 09:50:46      19368
20                   20130811 09:50:47      19368
ARCHIVING            20130811 09:50:48      19368

在会话级别重新设置不显示归档数据,可以看到只要是ORA_ARCHIVE_STATE字段不为0的记录都不会显示。

SQL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ACTIVE;

Session altered.

SQL> select INSERT_TIME,count(*) from TV group by INSERT_TIME order by 1;

INSERT_TIME         COUNT(*)
----------------- ----------
20130811 09:04:30          1
20130811 09:08:27          1
20130811 09:22:30          1
20130811 09:39:40          1
20130811 09:45:22          1

性能考虑,这一点数据库内归档与时间有效性是相同的,都只是对隐藏字段进行了filter操作。即使是只显示活跃数据,也仍然需要扫描全表。这一点在真实应用中可以通过创建索引来避免全表扫描,可以参看MOS Note: Potential SQL Performance Degradation When In Database Row Archiving (Doc ID 1579790.1),也就是数据库内归档只应该在一个具备良好性能的SQL基础上对返回结果进行过滤,而不要期望归档的记录不参与扫描

SQL> select * from TV;

INSERT_TIME
-----------------
20130811 09:04:30
20130811 09:08:27
20130811 09:22:30
20130811 09:39:40
20130811 09:45:22


Execution Plan
----------------------------------------------------------
Plan hash value: 1723968289

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     4 |  8044 |   102   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TV   |     4 |  8044 |   102   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("TV"."ORA_ARCHIVE_STATE"='0')

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        375  consistent gets
          0  physical reads
          0  redo size
        648  bytes sent via SQL*Net to client
        543  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          5  rows processed

数据库内归档可以跟时间有效性管理一起配合使用。在会话级别激活时间有效性,可以看到检索不再返回任何数据。执行计划中显示filter条件融合了数据库内归档跟时间有效性两层过滤。

SQL> exec dbms_flashback_archive.enable_at_valid_time('CURRENT');

PL/SQL procedure successfully completed.

SQL> select * from tv;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 1723968289

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     3 |  6087 |   102   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TV   |     3 |  6087 |   102   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("T"."ORA_ARCHIVE_STATE"='0' AND ("T"."VALID_TIME_START"
              IS NULL OR SYS_EXTRACT_UTC(INTERNAL_FUNCTION("T"."VALID_TIME_START"))<=S
              YS_EXTRACT_UTC(SYSTIMESTAMP(6))) AND ("T"."VALID_TIME_END" IS NULL OR
              SYS_EXTRACT_UTC(INTERNAL_FUNCTION("T"."VALID_TIME_END"))>SYS_EXTRACT_UTC
              (SYSTIMESTAMP(6))))


Statistics
----------------------------------------------------------
         34  recursive calls
          8  db block gets
        397  consistent gets
          0  physical reads
          0  redo size
        347  bytes sent via SQL*Net to client
        532  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

将时间有效期设置为20130811 09:39:50,根据上一篇文章我们设置的1分钟有效期,只有在20130811 09:39:40插入的这条活跃记录可以被显示出来。

SQL> exec dbms_flashback_archive.enable_at_valid_time('ASOF',to_date('20130811 09:39:50','YYYYMMDD HH24:MI:SS'));

PL/SQL procedure successfully completed.

SQL> select * from TV;

INSERT_TIME
-----------------
20130811 09:39:40


Execution Plan
----------------------------------------------------------
Plan hash value: 1723968289

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     3 |  6087 |   102   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TV   |     3 |  6087 |   102   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("T"."ORA_ARCHIVE_STATE"='0' AND ("T"."VALID_TIME_START"
              IS NULL OR INTERNAL_FUNCTION("T"."VALID_TIME_START")<=TIMESTAMP'
              2013-08-11 09:39:50.000000000') AND ("T"."VALID_TIME_END" IS NULL OR
              INTERNAL_FUNCTION("T"."VALID_TIME_END")>TIMESTAMP' 2013-08-11
              09:39:50.000000000'))


Statistics
----------------------------------------------------------
         35  recursive calls
          6  db block gets
        398  consistent gets
          0  physical reads
          0  redo size
        550  bytes sent via SQL*Net to client
        543  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

结论:数据库内归档是一个Oracle利用隐藏字段实现的非常简单的功能,但是数据架构人员在规划的时候一定要考虑性能因素。

【Oracle Database 12c New Feature】ILM – Temporal Validity

ILM全称是Information Lifecycle Management,意思是信息生命周期管理,听上去很高端洋气的一个词,但是实际上几乎每个稍微大些的系统都已经在做ILM了,比如说将生产表中的数据定期插入到历史表中,并把生产表中的这些数据删除,这就是数据生命周期管理;又比如使用了分区,定期将过期的数据分区删除掉,或者置为READONLY,让RMAN不再备份,这也是数据生命周期管理。

因此ILM由来已久,只要数据存在活跃-不活跃-静止这样的周期变化,那么ILM就必不可少,Oracle Database 12c中提供了很多新功能用来方便地进行数据生命周期管理,有些功能甚至是我们期盼已久的。

本文先介绍时间有效期管理(Temporal Validity),下两篇文章会介绍数据库内归档(In-Database Archiving)以及数据热度图(Heat Map)。注意:Temporal Validity和Heat Map目前还不支持多租户架构的数据库,因此想要使用,必须是一个NON-CDB,In-Database Archiving则支持多租户架构,可以在PDB中使用。

一. 时间有效期管理(Temporal Validity)
以下简称TV,TV的功能大致上可以这样描述:在表中手动或者自动建两个时间类型的字段,一个表示有效期的开始时间,一个表示有效期的结束时间,就可以通过设置让只有在有效期内的记录才会被选择出来。

以下这个场景是我构想出来的,一张表里不断地INSERT数据,但是每条数据有效期只有1分钟,过了1分钟再查就看不见了,如果加以仔细策划,应该会是很有趣的功能。直接进入测试。

设置TV,需要使用dbms_flashback_archive包,需要该包的执行权限。

SQL> grant execute on dbms_flashback_archive to kamus;

创建测试表,period for关键字是TV新功能的关键字,valid_time是TV策略的名字,可以随便写。valid_time_start和valid_time_end字段可以不手工定义,只要指定了period for关键字,Oracle会自动创建两个不可见字段。我这里之所以手工定义开始和结束时间字段,是为了能够指定DEFAULT值。有效期开始时间valid_time_start是记录插入的当前时间,有效期结束时间valid_time_end是当前时间的后一分钟。由此定义出了一个跨度1分钟的有效期。

SQL> conn kamus/oracle
SQL> create table TV (insert_time date, 
valid_time_start date invisible default sysdate, 
valid_time_end date invisible default sysdate+1/1440, 
period for valid_time(valid_time_start,valid_time_end)
);

可以看到明确定义的INSERT_TIME字段用于演示,VALID_TIME_START和VALID_TIME_END是明确定义的不可见字段。之外,Oracle还自动创建了VALID_TIME字段,也是隐藏字段。

SQL> select COLUMN_NAME,DATA_TYPE,HIDDEN_COLUMN FROM USER_TAB_COLS WHERE TABLE_NAME='TV';

COLUMN_NAME          DATA_TYPE            HID
-------------------- -------------------- ---
VALID_TIME_END       DATE                 YES
VALID_TIME_START     DATE                 YES
INSERT_TIME          DATE                 NO
VALID_TIME           NUMBER               YES

插入一行当前时间

SQL> insert into TV values (sysdate);

1 row created.

正常情况选择,这行记录总是存在的

SQL> select * from TV;

INSERT_TIME
-----------------
20130811 09:04:30

为了应对这个新功能,在Flashback Query中新增了as of period for关键字。as of period for valid_time sysdate+1表示我们想查询在明天都还有效的数据,因为根据我们的设定,所有数据都只在插入以后1分钟内有效,因此自然无法找到在明天还有效的数据,返回零条记录。

SQL> select * from TV as of period for valid_time sysdate+1;

no rows selected

再插入一条测试数据。

SQL> insert into TV values (sysdate);

1 row created.

SQL> select * from TV;

INSERT_TIME
-----------------
20130811 09:04:30
20130811 09:08:27

我们想查询昨天就有效的数据,但是所有的数据有效期开始都是插入数据的那个时间点,自然无法找到昨天就有效的数据,返回零条记录。

SQL> select * from TV as of period for valid_time sysdate-1;

no rows selected

除了使用as of这种闪回查询的语法,还可以直接在会话级别设置有效时间点。CURRENT表示设置为当前时间点。

SQL> exec dbms_flashback_archive.enable_at_valid_time('CURRENT');

PL/SQL procedure successfully completed.

SQL> select * from TV;

no rows selected

在我的测试过程中,TV并不稳定,有时候即使设置了as of,也仍然会返回所有记录,但是过一会儿再次执行完全相同的语句,又能够返回符合条件的记录。没有详细跟踪不稳定的原因,但是猜测与cursor执行计划重用有关,毕竟Oracle的实现只是增加了一个filter条件,如果由于某种原因,之前cursor的执行计划被重用,那么很可能这个filter条件就没有加上,随之而来的也就会返回所有记录。

接下来,我们通过显示执行计划,看看Oracle是如何增加这个filter条件的。
首先禁用TV。执行计划是很正常的全表扫描。

SQL> exec dbms_flashback_archive.DISABLE_ASOF_VALID_TIME;

PL/SQL procedure successfully completed.

SQL> select count(*) from tv;

  COUNT(*)
----------
     77477


Execution Plan
----------------------------------------------------------
Plan hash value: 4129329588

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   102   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TV   | 76349 |   102   (0)| 00:00:01 |
-------------------------------------------------------------------

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        333  consistent gets
          0  physical reads
          0  redo size
        544  bytes sent via SQL*Net to client
        543  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

重新在会话级别启用TV,可以看到在第二步,也就是全表扫描之后增加了一个filter,由于指定的有效期是CURRENT,因此filter条件是VALID_TIME_START 小于等于 当前时间 小于 VALID_TIME_END,也就是只要指定的有效期落在VALID_TIME_START和VALID_TIME_END之间,这条记录就可以被显示出来。同时也可以看到如果这两个限制条件为空,也都作为开放区间,也就是为空就表示不做限制。
由于测试的记录都只有1分钟有效期,因此此时已经没有一条记录可以显示了。

SQL> exec dbms_flashback_archive.enable_at_valid_time('CURRENT');

PL/SQL procedure successfully completed.

SQL> select count(*) from tv;

  COUNT(*)
----------
         0


Execution Plan
----------------------------------------------------------
Plan hash value: 4129329588

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    18 |   103   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |    18 |            |          |
|*  2 |   TABLE ACCESS FULL| TV   |   287 |  5166 |   103   (1)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(("T"."VALID_TIME_START" IS NULL OR
              SYS_EXTRACT_UTC(INTERNAL_FUNCTION("T"."VALID_TIME_START"))<=SYS_EXTRACT_
              UTC(SYSTIMESTAMP(6))) AND ("T"."VALID_TIME_END" IS NULL OR
              SYS_EXTRACT_UTC(INTERNAL_FUNCTION("T"."VALID_TIME_END"))>SYS_EXTRACT_UTC
              (SYSTIMESTAMP(6))))


Statistics
----------------------------------------------------------
         33  recursive calls
          4  db block gets
        354  consistent gets
          0  physical reads
          0  redo size
        541  bytes sent via SQL*Net to client
        543  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

通过执行计划显示后台机制是一方面,另一方面我们也可以看到实际上TV是会有性能问题的,如果WHERE条件中无法使用到索引而执行了全表扫描(我这里因为没有WHERE条件所以只能是全表扫描),那么无论最终符合有效期的记录是多少,总要先进行所有记录的扫描,我们可以通过前后两次的consistent gets基本相同来获得这个结论。

更直白的说,如果作为系统设计人员不去考虑索引的构建,而仅仅是启用了TV,那么哪怕根据有效期限制,有10万记录的表只有1条会被显示出来,也仍然需要先扫描10万记录,然后再filter掉99999条,这对于程序员来说,如果不仔细阅读执行计划,就可能会造成很大的困扰,程序员会很奇怪,为什么这张表里面看上去只有1条记录,但是却要扫描那么长时间呢?

结论:数据有效期是Oracle利用隐藏字段和Flashback Query技术作的一个有趣的功能,但是数据架构人员在规划的时候一定要考虑性能因素。

OOW US Travel Tips for ACE Director – Visa, Hotel, Car Rental, etc.

因为我个人是比较早接受Oracle邀请去美国旧金山参加Oracle Open World的ACE Director,而且又带老婆一块儿去过,也租车自驾过,总体来说经验比较丰富,把这些经验写出来,希望对新的ACED会有帮助。

一. 大致流程
6月到7月之间,所有的ACE Director会收到一封邀请参加当年在旧金山举办的Oracle Open World的邮件,在邮件里面会有一个URL需要点进去接受这个邀请,链接里面会有一些问题需要回答,邮件里面也会明确说明接受这个邀请的Deadline日期,所以如果想去参加那么一定要早些接受邀请。

8月中旬,所有接受了邀请的ACE Director又会再收到一封邮件,这次是要注册OOW了,这封邮件会比较长,有很多需要作的事情,后面详细解释。

9月底或者10月初,一年一度的OOW在旧金山举办,主会场永远是旧金山市中心的Moscone Center,ACED入住的酒店永远是Hilton Union Square,从酒店可以步行到会场,中间会路过旧金山的Apple Store。

二. 签证
很多人担心签证会不过,但是就我的经验,参加OOW的签证申请还没有被拒签过,对于首次作美国签证的ACED来说,最好是要Oracle发一封正式邀请函传真件过来(其实心大一些,用Oracle发过来的邀请邮件打印版也是可以的),如果你想带夫人一起前往,那么可以要求邀请函的抬头写上你跟你夫人两个人的名字。

如果不是首次去,那么其实根本就无需等Oracle发给你邀请,觉得时间差不多,就可以自己申请签证了。

今年美国签证的整体流程都发生了变化,需要在CGI网站上先注册预约,然后再进行后续步骤。对于首次签证的需要面签,对于已有签证并且失效不超过4年的(4年哦,48个月呢)只需要让中信银行代传递材料即可。

简单描述一下流程,由于新版流程以后,我不需要面签,因此对于面签流程不熟悉。以下描述为”代传递“流程。
1. 在线填DS160表格,表格比较冗长,不在这里描述了,初填者大概要花1个小时吧。其中有个姓名的telecode,可以通过标准中文电码网站查询。最后有一个Confirmation页面,这个页面要打印出来,上面的确认编号也要记好,后面有用。

2. CGI网站注册,然后登录进去,开始CGI预约。
1) 点击左边菜单最上面的“安排面谈时间”,开始填。
Screen Shot 2013-08-13 at 12.56.27 AM
2) 选择预约使馆时,如果是第一次,选择离你工作地点最近的使馆,如果不需要面签,那么选择最后一项“免面谈代传递服务”。
Screen Shot 2013-08-13 at 12.58.48 AM
3) 签证类型选择Businese/Tours,也就是B1/B2,又表示参加会议又表示要游玩,我一直是这么选的,当然你也可以只选择B1。
4) 填信息的页面有一个地方需要输入DS160确认编号。
5) 到Step 7的时候出现BUG了,无论你在预约类型那里选的是不是“免面谈代传递服务”,这里都会问“是否在DS-160签证申请表格上选择“中国,广州”作为您此次签证的申请地点?”,这里要点“是”,才可以进入到下面的问题,否则就直接进入预约面谈日期的界面了。
6) 指定护照/文件送达地址选择里面,都是中信银行的位置,选择一个离你最近的即可。
7) 进入录入收据编号的页面了,收据是个什么东西?签证是要签证费的,不到1000人民币,交了费就给你一个收据,上面有个编号就是收据编号,以前是直接去中信银行缴纳,现在可以直接在网上交了,点击“点击这里选择付款选项”。
Screen Shot 2013-08-21 at 3.48.09 PM
然后选择右边的“中国中信银行”。即使是准备网上缴费也要选择中信银行,而不是左边的“借记卡”,不要被“在银行柜台付款”的字样迷惑了。
Screen Shot 2013-08-21 at 3.48.26 PM
然后就可以到中信金融商城中去网上缴费,缴费完毕以后返回Step 8的页面自动就帮你填入收据编号了。注意这个页面最上方的CGI Reference Number在缴款的时候是有用的。网上很多人问CGI Number到底从哪里查?就是在这儿。
Screen Shot 2013-08-21 at 3.48.40 PM

8) 最后就是”DropBox Confirmation“页面,点击”可打印版本“,然后打印出来。

3. 把材料带齐去中信银行,交给柜台即可。材料包括:
1) DS160表格确认页;
2) DropBox Confirmation打印页;
3) 护照;
4) 一张美国签证专用照片(要求6个月内近照,但是我还是用去年的照片也OK)。

4. 大约6-8个工作日之后,签证会办好,寄回你之前在CGI网站选择的地址,并且有邮件通知你去取。
Screen_Shot_2013-08-15_at_6.40.13_PM
邮件大致如上面所示,不要被其中不专业的翻译“退回”所吓到,实际上英文是Returned,记好邮件中提到的UID,到了中信银行,告诉他们UID和你的姓名,很快你就可以拿到盖着热腾腾的亚美利加VISA的护照了。

三. 机票酒店
ACED的机票Oracle会帮买,不用自己买,但是如果要带其它人一起去,切记切记最重要的一点,越早买机票越好。三四月份就定的话,直飞大约能拿到往返6000多的价格,五六月份订大约是往返8000多,现在8月份我查大约是12000,再往后就没谱了。
1. 拒签的可能性很小,不需要一定等着签证出来了,再去买机票。
2. 即使被拒签,大不了就是退票,退票费大约1500人民币,但是如果一直等到签证办完再出机票,那么一定不止贵了1500元,算一算,也知道越早买是越划算的。

因为ACED自己的机票酒店,都是Oracle帮助预订的,因此实际上对于ACED自己来说,需要自己搞定的就是美国VISA而已,其它的只需要按照Oracle的节奏一步一步该注册的注册,该发邮件的发邮件即可。以下简单描述让Oracle帮助预订机票酒店的步骤。

1. Oracle处理全球所有ACED行程的人似乎只有美国总部的大美女Lillian一个人,因此节奏有些慢是正常的,给Lillian发邮件她没时间回复也是正常的,不用着急,只要是ACED,每年一定会被邀请到,也一定会被Approve,所以根本无需担心是不是会被批准啊这样的问题。
2. 在前面的大致流程中也提到,6月到7月之间,会收到一个邀请参加OOW的邮件,按照这封邮件的指引,在某个网站回答一些问题,只是表示你愿意接受邀请,之后很长时间会没有任何反馈,这段时间是Oracle在准备OOW,所以等着就好了。
3. 到了8月中旬,Oracle的OOW准备也差不多有眉目了,这时候所有的ACED又会收到一封邮件,这封邮件的内容就丰富了,要做的事情也很多。

首先这封邮件会描述在整个OOW期间专门为ACED准备的活动日程,“Oracle ACE Activities during Oracle OpenWorld”部分。其中最重要的两个活动是:
ACE Director Product Briefing:这是一个通常会在OOW的前两天举行的一个两天的小型会议,邀请全球的ACED参加,在这个会议上会有Oracle各个产品线的总监级人物,预先透露一些会在OOW中宣布的产品新特性,回答ACED的问题,这实际上是给ACED与Oracle更近的交流距离。这个会议会在Oracle总部举行,因此如果想去膜拜一下Oracle总部大楼的话,应该去参加。要知道OOW是在旧金山举办,离Oracle总部所在的Redwood Shore实际上是两个城市了,有不近的距离。
Annual Oracle ACE Dinner:就是饭局了,通常是在OOW第一天的晚上,会有车把所有参加的ACED拉到一个地方,每年吃饭的地方不太一样,如果想认识全球更多的ACED,或者跟老熟人扯扯淡,这个饭局是要去参加的。我通常都在这个饭局里面邀请来年能够来中国参加Oracle技术嘉年华大会的演讲嘉宾。

接下来这封邮件会提到注册OOW,“BLOGGER REGISTRATION”部分。点击邮件里的链接即可,通常每个ACED都是blogger,因此都会注册blogger类型的OOW入场券,blogger类型的入场券适用范围最广,不但可以参加OOW还可以参加Java One,而且在Larry作Keynote的现场会有专门的一个区域,配备了桌椅让你一边听一边发推。跟着注册页面走就行了,会看到门票价格已经自动变为0美元。注册完毕以后,会立刻收到一封确认邮件,主题类似于“Oracle San Francisco 2013 Registration Confirmation”,这封邮件明确提到“Please note that your registration is not confirmed until you receive that approval e-mail.”,也就是这封邮件只是表示收到了你的OOW注册请求,还没有被正式批准,要等下一封批准邮件。但是不用担心,一定会被批准的。

再接下来,需要作的事情就是申请机票,“TRAVEL RESERVATIONS”部分。Oracle的机票预订是交给专门的公司CWT来完成的,邮件中会提到给某个美国电话打电话,或者发邮件到一个地址,对于中国人来说通常都是选择发邮件了。
邮件内容大致应该包括:Group#(这是最重要的,邮件中会提到这个#,因为你的名字已经预先包含在这个Group#中,CWT收到这个#才知道你是ACED来预订机票的),出发和返回的日期,期望乘坐的航班号,乘机人姓名,护照号。
我一般会选国航的CA985(北京-旧金山)和CA986(旧金山-北京),每天一班北京-旧金山往返的飞机,选择国航的一个好处是,如果有国航知音卡,往返一趟美国的积分大约可以换一张去国内任何一个城市的机票了。
发出邮件以后,通常在48小时之内就会有邮件回复,如果你的行程拉的比较长(比如参加完OOW还想在美国玩一段时间),那么可能会遇到说由于你回程太晚,机票价格贵了,所以要额外再提交审批,请你等待。等着就好。

而对于酒店预订,“HOTEL ACCOMMODATIONS”部分,先不要着急,要等着收到了注册OOW的批准邮件之后,再去更新自己的Profile,那时候就会看到有Add Hotel的链接,点进去,输入邮件中提到的专门给ACED提供的预订码(booking code)。
Screen Shot 2013-08-20 at 3.14.40 AM
然后就会自动将Hilton Union Square酒店显示出来了,点选你的入住和离店日期,之后还需要输入一个信用卡号,虽然可以看到每天晚上有数百美金的房费,但是不用担心,预订是不会charge信用卡钱的,入住完毕结账的时候也不会扣款,房费直接会从Oracle结算。

对于参加ACE Director Product Briefing的ACED,不需要任何预订流程,Oracle会自动安排好入住的酒店,到了以后直接入住即可。今年是在Redwood Shores的Sofitel,酒店的名字在邮件中可以找到。

四. 租车
欧洲的租车网站会很便宜,不确定是什么原因,这些网站都是聚合了Herz, Alamo, Dollar, Fox等租车公司的信息,可以从容比价。我最常用的是两个网站,一个是Carhire 3000,通常这个网站的价格是最便宜的,需要用欧元结账;另外一个网站是Holiday Cars,这个网站上Fox租车公司的SUV出奇的便宜,有时候会比普通小车还便宜。

在美国租车有几点需要考虑:
1. 保险:这两个网站租车都带了所有的基本保险。如果要购买额外的人身保险还是很贵的,建议直接在国内买个国外旅游险就OK了。
2. 额外驾驶员:基本价格通常都只有一个驾驶员,有些会写着包含了Additioanl Driver,如果没写,那么期望多个人开车的时候,要另行购买,否则如果被美国警察拦住,可能会被罚的很惨。我们没遇到过。
3. 一箱油:交车给你的时候,都是一箱满油,有些是换车的时候不论是不是油箱空了,都要再直接付一箱油钱;有些是换车的时候,你自己找个地方加满就好了,因为租车公司卖出来的一箱油通常较贵,因此两种方法会有细微的差别,但是相差无几,所以不用考虑过多。
4. GPS:如果你没有自带GPS,也没有美国的朋友可以借给你,那么就需要租一个,每天大约10美金,也不便宜。

五. 其它Tips
1. 到了酒店以后,是要出示信用卡的,为了有额外的消费时可以直接扣款(Oracle只负责每晚基本的房费)。
2. Hilton Union Square的房间宽带网络是要额外付费的,而且是按每个Device收费的,也就是一台笔记本,一个手机算两个Device。如果不想交钱可以到一楼大厅用免费的Wifi。
3. 美国酒店退房一般不需要退还房卡,直接走人就可以了。如果有任何额外消费,酒店会自动从你入住时出示的信用卡中扣款。
4. 美国是小费国家,入住酒店以后通常每天早上要在枕头上放1美元留给房间服务员,当然,如果你死活不愿意放也不会有什么事儿。

【未完待续】