OceanBase 2.1 的ORACLE兼容性能力探秘
概述
OceanBase是一款通用的分布式关系型数据库,目前内部业务使用比较多有两个版本:1.4和2.1。OceanBase每个版本变化总能带给人很多惊喜,其中2.1版本实现了ORACLE很多特性的兼容。本文主要简单浏览一下这些新功能。
运维
账户管理
在ORACLE Mode的租户里,创建用户依然是create user
命令,密码不用单引号。授权方式还是还是ORACLE和MySQL的结合。查看权限方式是MySQL的语法(这点还是MySQL语法很方便)。
在ORACLE Mode的租户里,不同用户就是不同SCHEMA
,默认彼此数据访问权限隔离,除非明确授权访问。
$obclient -h11.***.84.84 -usys@tnt_oracle#obdemo -P2883 SYS -A -pobDBA2019
create user ora_user identified by 123456;
grant all privileges on ora_user.* to ora_user;
grant select on sys.* to ora_user;
show grants for ora_user;
select username, account_status, lock_date, expiry_date, created from dba_users;
实例变量查看
OceanBase集群级别的参数是通过查看和修改parameters
,但是在Oracle租户里,租户级别的设置修改依然是通过类似修改MySQL的变量(variables
)来的。这点跟Oracle原生实例不一样。
show global variables where variable_name in ('autocommit','ob_compatibility_mode','ob_enable_sql_audit','ob_query_timeout','ob_read_consistency','ob_tcp_invited_nodes','ob_trx_timeout','sql_mode','tx_isolation','system_time_zone','time_zone');
修改方法举例
set global autocommit=on;
性能分析
OceanBase实现了很多类似Oracle的AWR相关的GV$
视图。不过大部分在业务租户下是没有权限查看的。业务租户下只提供了一个SQL全量日志视图。这个也够用了。详细用法参见《阿里数据库性能诊断的利器——SQL全量日志》
select /*+ read_consistency(weak) query_timeout(1000000000) */ request_time, svr_Ip, trace_id, sid, client_ip, tenant_id,tenant_name,user_name,db_name, query_sql, affected_rows,ret_code, event, state, elapsed_time, execute_time, queue_time, decode_time, get_plan_time, block_cache_hit, bloom_filter_cache_Hit, block_index_cache_hit, disk_reads,retry_cnt,table_scan, memstore_read_row_count, ssstore_read_row_count, round(request_memory_used/1024/1024) req_mem_mbfrom gv$sql_audit where user_name in ('ora_user') and rownum<100order by request_time desc ;
开发
面向开发的功能主要就是DDL
和DML
了。
DDL
建表
OceanBase的表是索引组织表(IOT
),强烈建议设置主键,并且主键就是数据。
建表时支持的数据类型如下:
-
CHAR
/VARCHAR2
-
DATE
/TIMESTAMP
/TIMESTAMP WITH TIME ZONE
/TIMESTAMP WITH LOCAL TIME ZONE
-
INTERVAL
(部分运算) -
NUMBER
(包括其子类型int
等) -
CLOB
/BLOB
(不超过48M)
建表示例:
$obclient -h11.***.84.84 -uora_user@tnt_oracle#obdemo -P2883 -A -p123456 ORA_USER
create table t01(
id number not null,
c1 char(10),
c2 varchar2(10),
c3 DATE default sysdate,
c4 timestamp default systimestamp,
c5 timestamp with time zone default localtimestamp,
c6 timestamp with local time zone default localtimestamp,
c7 int,
c8 clob,
c9 blob
);
create sequence seq_t01 start with 1000000000 increment by 2 cache 100 ;
insert into t01(id, c1, c2, c7, c8)
values(seq_t01.nextval, 'test', 'test',99999999999,'clobtextclobtextclobtextclobtextclobtextclobtextclobtextclobtextclobtext');
select * from t01\G
支持通过CTAS
方法从老表创建新表。
修改表结构
目前对修改表结构类型还有很多限制,如只能在同类类型中改大值域。如varchar
扩大长度。
函数
目前支持ORACLE常用的函数。如时间函数、数值函数、字符串函数、类型转换函数、条件函数、系统函数、统计分析函数等等。
时间函数
目前支持:
-
interval
-
localtimestamp
-
current_timestamp
-
sysdate
/systimestamp
select sysdate, sysdate + interval'1' minute next_min, sysdate + interval'1' hour next_hour, sysdate + interval'1' day next_day from dual;
数值函数
目前支持:
-
abs
/sign
-
floor
/'ceil` -
trunc
/mod
-
bitand
示例如下:
select abs(-3.1415926), ceil(3.1415926), floor(3.1415926), sign(-3.1415926),round(314 / 7, 0), mod(314,7), trunc(3.1415926) f
rom dual;
比较函数
目前支持:
-
least
/greatest
字符串函数
目前支持:
-
pad
/lpad
/rpad
-
instr
/substr
-
concat
/||
-
length
/lengthb
-
lower
/upper
select lpad(3.14159, 10, '*') c1, rpad('Apple', 10, '<') c2, ltrim(' Hello') c3, rtrim('World! ') c4, 'Hello ' || ' World' c5, concat('Hello ',' World!') c6, lower('Hello World!') c7, upper('Hello World!') c8, instr('Hello World','o',6) c9, substr('Hello World',5,3) c10, length('Hello 中国!') c11, lengthb('Hello 中国!') c12 from dual;
类型转换函数
主要是数值、字符串、日期之间的互相转换
目前支持:
-
to_date
/to_timestamp
-
to_char
-
to_number
示例如下:
select cast('3.1415926' as number), to_date('2019-05-23 14:00:00','yyyy-mm-dd hh24:mi:ss'), to_number('3.1415926'), to_char(3.1415926), to_timestamp(sysdate), to_timestamp_tz(sysdate) from dual;
条件函数
目前支持:
-
case...when...end
-
nvl
-
decode
drop table t02;
create table t02(id number not null , type varchar2(2), gmt_create date not null default sysdate);
insert into t02(id,type) values(1,'R'),(2,'B'),(3,NULL);commit;
select id, NVL(type,'NULL!') type, case type when 'R' then 'Good guy!' when 'B' then 'Bad guy!' else 'Unknown!' end type_desc,
decode(type,'R','Good guy!','B','Bad guy!','Unknown!') type_desc2, gmt_create
from t02;
系统函数
目前支持:
-
uid
/user
select uid, user, userenv('schemaid'),SYS_CONTEXT('userenv','current_user') from dual;
select rownum rn,object_name, object_type from user_objects order by object_name;
分析函数
目前支持的聚合函数包括:
-
COUNT
-
APPROX_COUNT_DISTINCT
-
SUM
,MAX
,MIN
,AVG
-
LISTAGG
,RANK
,DENSE_RANK
,PERCENT_RANK
+ROW_NUMBER
-
NTILE
,CUME_DIST
,FIRST_VALUE
,LAST_VALUE
-
LEAD
,LAG
,NTH_VALUE
示例如下:
统计组内排名
select customernumber, checknumber, paymentdate, amount, dense_rank() over (partition by customernumber order by amount) dense_rank ,
round(PERCENT_RANK() over (partition by customernumber order by amount),2) perentage
from payments where customernumber=141 order by dense_rank, customernumber;
统计数量近似值
select count(distinct customernumber), APPROX_COUNT_DISTINCT(customernumber) from payments;
统计分组汇总
select * from (
select OFFICECODE, listagg(LASTNAME,',') within GROUP (ORDER BY EMPLOYEENUMBER) OVER (partition by OFFICECODE) EMP_LIST,
row_number() over (partition by OFFICECODE order by EMPLOYEENUMBER) as rn
FROM employees)
where rn = 1;
统计分组内第一和最后一个值
select OFFICECODE, listagg(LASTNAME,',') within GROUP (ORDER BY EMPLOYEENUMBER) OVER (partition by OFFICECODE) EMP_LIST,
first_value(LASTNAME) over (partition by OFFICECODE order by EMPLOYEENUMBER ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) first_emp_all,
last_value(LASTNAME) over (partition by OFFICECODE order by EMPLOYEENUMBER ) last_emp,
last_value(LASTNAME) over (partition by OFFICECODE order by EMPLOYEENUMBER ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) last_emp_all
FROM employees
order by OFFICECODE;
同行显示分组统计的上一个和下一个值
select customernumber, checknumber, paymentdate,amount, round(cume_dist() over (partition by customernumber order by amount) ,2) as cume_dist ,lag(amount) over (partition by customernumber order by amount) last_ck,lead(amount) over (partition by customernumber order by amount) next_ckfrom payments where customernumber in (412,447,452,458) order by customernumber;
后记
更多Oracle的兼容性还在陆续开发或内部试用中。尤其是存储过程、PLSQL
以及Package
。请保持关注。
OceanBase对Oracle的兼容只是用户功能接口上的兼容,其底层原理依然是OceanBase特有的原理。
推荐阅读
更多后续分享敬请关注公众号:obpilot