问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

oceanbase认证有必要考吗

发布网友 发布时间:2022-04-21 00:13

我来回答

2个回答

懂视网 时间:2022-04-12 22:28

一、 什么是逻辑计划?

我们已经知道,语法树就是一个树状的结构组织,每个节点代表一种类型的语法含义。如
update student set sex="M" where name ="小明";
这条SQL的语法树形状为:

|Update Stmt
|----Table:student
|----TargeList:
|--------sex = "M"
|----Qualifications:
|--------name="小明"

但是仅仅语法树并不能知道数据库中是否存在student这张表,这张表是否有sex,name这两个字段,我们是否有权限修改这条记录等。语法树只能判断这条SQL的写法是否正确,不能确定这条SQL是否可以执行。

逻辑计划需要明确SQL语句中所涉及到的表,字段,表达式等是否有效。这个的逻辑计划与在《数据库系统实现》等书中描述的逻辑查询计划不同。逻辑查询计划将SQL语句直接转为可运算的关系表达式。在OceanBase中,逻辑计划则只是查找或生成涉及到的表的ID,涉及字段的ID,涉及表达式的ID等,逻辑计划是不可运算的。

二、逻辑计划包含哪些内容?

简单来说,逻辑计划要弄清楚,这条SQL可以分解为几条stmt,每条stmt包含了哪些表,字段和表达式。在此基础上,如果是insert的Stmt,要加上设置哪些值;如果是update的stmt,要加上需要更新的列和对应的值,等等。

在一个逻辑计划中,每一个查询有一个唯一标识qid,每一张表有一个唯一的标识tid,每一个列有一个唯一的标识cid,每一个表达式有一个唯一的标识eid。

来看OceanBase中的逻辑计划的结构(省略无关方法和变量).

 class ObLogicalPlan
 {
 //... 
 oceanbase::common::ObVector stmts_; //存储该逻辑计划的所有stmt
 oceanbase::common::ObVector exprs_; //逻辑计划的所有表达式
 oceanbase::common::ObVector raw_exprs_store_;//存储逻辑计划的所有表达式
 uint64_t new_gen_tid_;//用于生成新的tid
 uint64_t new_gen_cid_;//用于生成新的cid
 uint64_t new_gen_qid_;//用于生成新的qid
 uint64_t new_gen_eid_;//用于生成新的eid
 };

oceanbase::common::ObVector是OceanBase中自己实现的泛型容器之一,作用与STL的vector相同。
stmts_存储该逻辑计划的所有stmt;
raw_exprs_store_仅仅用于存储表达式,exprs_则引用raw_exprs_store_中的内容。
new_gen_tid_等4个变量是用来生成新的标识时使用,一个逻辑是可以用多个tid,多个cid,多个eid,多个qid的。这些标识分布于存储的stmt和表达式中。

注:stmt实在不知道中文该怎么称呼,就不改中文名了。

2.1 逻辑计划中表的定义


struct TableItem
{
 uint64_t table_id_;
 common::ObString table_name_;
 common::ObString alias_name_;
 TableType type_;

 uint64_t ref_id_;
};

table_id_唯一标识一个关系表,其类型分为基本表,引用表和子查询关系。
对同一个实体表,ref_id_table_id_相同; 如果是一个引用别名的表,则table_id_是新生成的,ref_id_与这个表真正的table_id_相同;如果是一个子查询,则table_id_是新生成的,ref_id_是对子查询的引用。

对同一个实体表,它在所有线程使用的table_id_都是相同的;如果是生成的标识,则仅在该线程会话期间是唯一的。

2.2 逻辑计划中列的定义

struct ColumnItem
{
 uint64_t column_id_;
 common::ObString column_name_;
 uint64_t table_id_;
 uint64_t query_id_;

 bool is_name_unique_;
 bool is_group_based_;

 common::ObObjType data_type_;
};

column_id_唯一标识一个列,table_id_query_id_为该列所属的关系表和stmt。is_name_unique_仅用在解析逻辑计划期间,标记该列的名称是否在所有表的字段中都是唯一的。is_group_based_标记该列是否用于分组。data_type_标识该列的数据类型。

2.3 逻辑计划中的表达式的定义

逻辑计划的中表达式有多种类型,其基类为ObRawExpr.包括两个成员变量,type_表示表达式的类型,result_type_表示表达式值的类型。

 class ObRawExpr
 {
 //省略其他方法
 private:
 ObItemType type_;
 common::ObObjType result_type_;
 }

表达式分为常量表达式, 一元引用表达式,二元引用表达式,一元操作符表达式,二元操作符表达式,三元操作符表达式,多元操作符表达式,case操作符表达式,聚集函数表达式,系统函数表达式,SQL原生表达式等。继承关系如下。

namespace sql
{
 //原生表达式基类
 class ObRawExpr
 //常量表达式
 class ObConstRawExpr : public ObRawExpr
 //一元引用表达式
 class ObUnaryRefRawExpr : public ObRawExpr
 //二元引用表达式
 class ObBinaryRefRawExpr : public ObRawExpr
 //一元操作符表达式
 class ObUnaryOpRawExpr : public ObRawExpr
 //二元操作符表达式
 class ObBinaryOpRawExpr : public ObRawExpr
 //三元操作符表达式
 class ObTripleOpRawExpr : public ObRawExpr
 //多元操作符表达式
 class ObMultiOpRawExpr : public ObRawExpr
 //case操作符表达式
 class ObCaseOpRawExpr : public ObRawExpr
 //聚集函数表达式
 class ObAggFunRawExpr : public ObRawExpr
 //系统函数表达式
 class ObSysFunRawExpr : public ObRawExpr
 //SQL原生表达式
 class ObSqlRawExpr  : public ObRawExpr
 };

 class ObRawExpr
 {

 };

在ObLogicalPlan中,存储使用的是vector,使用时转为vector.

2.4 逻辑计划中的Stmt的定义

Stmt表示一个单独的查询所包含的内容,一个逻辑计划可以包含多个Stmt.

 class ObStmt
 {
 /*省略部分内容...*/
 protected:
 common::ObVector table_items_;
 common::ObVector column_items_;

 private:
 StmtType type_;
 uint64_t query_id_;
 //uint64_t where_expr_id_;
 common::ObVector where_expr_ids_;

 };

Stmt包括了一个查询所有的表table_items_,列column_items_,表达式where_expr_ids_和一个唯一的查询标识query_id_。注意这里存储的只有表达式的id,而不是表达式的实际内容。

从上述的定义总结来看,一个逻辑计划拥有多条查询实例Stmt和多个表达式,一个查询实例Stmt包含了多个表和多个列及所需表达式的引用。表,列,表达式,查询实例都有唯一的标识符进行标记。

ObLogicalPlan
----ObStmt : 1...n
--------TableItem : 0...n
--------ColnumItem : 0...n
--------expr_id_ref : 0...n
----ObRawExpr : 0...n

三、 如何制定逻辑计划?

3.1 reslove系列解析函数

制定逻辑计划的源码在build_plan.h和build_plan.cpp中,在OceanBase0.4中,则增加了dml_build_plan.h和dml_build_plan.cpp。制定逻辑对外提供的接口只有两个,解析函数resolove和销毁函数destroy_plan,其他的为自用,可以浏览下其函数声明及用途,基本的结构就是这样,因为目前OceanBase中支持的SQL语句不多,相应的解析函数也比较少,还有一些没有完成,可以想见未来还会添加更多的函数。

//解析多重查询
int resolve_multi_stmt(ResultPlan* result_plan, ParseNode* node)
//解析独立表达式
int resolve_independ_expr()
//解析and表达式
int resolve_and_exprs()
//解析表达式
int resolve_expr()
//解析聚集函数
int resolve_agg_func()
//解析join表连接
int resolve_joined_table()
//解析表
int resolve_table()
//解析from子句
int resolve_from_clause()
//解析列
int resolve_table_columns()
//解析*
int resolve_star()
//解析select的投影列表
int resolve_select_clause()
//解析where子句
int resolve_where_clause()
//解析group by子句
int resolve_group_clause()
//解析having子句
int resolve_having_clause()
//解析order子句
int resolve_order_clause()
//解析limit子句
int resolve_limit_clause()
//解析select查询
int resolve_select_stmt()
//解析delete查询
int resolve_delete_stmt()
//解析insert的插入列
int resolve_insert_columns()
//解析intsert查询的插入值
int resolve_insert_values()
//解析insert查询
int resolve_insert_stmt()
//解析update查询
int resolve_update_stmt()
//解析函数。对外提供
int resolve(ResultPlan* result_plan, ParseNode* node)
//销毁函数,对外提供
extern void destroy_plan(ResultPlan* result_plan)

resolve函数根据语法树node的类型调用不同的查询解析实例。以下是部分代码摘抄:

int resolve(ResultPlan* result_plan, ParseNode* node)
{
 /*...*/

 uint64_t query_id = OB_INVALID_ID;
 if (ret == OB_SUCCESS && node != NULL)
 {
 switch (node->type_)
 {
 case T_STMT_LIST:
 {
 ret = resolve_multi_stmt(result_plan, node);
 break;
 }
 case T_SELECT:
 {
 ret = resolve_select_stmt(result_plan, node, query_id);
 break;
 }
 case T_DELETE:
 {
 ret = resolve_delete_stmt(result_plan, node, query_id);
 break;
 }
 case T_INSERT:
 {
 ret = resolve_insert_stmt(result_plan, node, query_id);
 break;
 }
 case T_UPDATE:
 {
 ret = resolve_update_stmt(result_plan, node, query_id);
 break;
 }
 default:
 ret = OB_ERROR;
 break;
 };
 }
 return ret;
}
int resolve_update_stmt(ResultPlan* result_plan, ParseNode* node, uint64_t& query_id)
{
 int& ret = result_plan->err_stat_.err_code_ = OB_SUCCESS;
 uint64_t table_id = OB_INVALID_ID;

 query_id = OB_INVALID_ID;

 ObLogicalPlan* logical_plan logical_plan = new(logical_plan) ObLogicalPlan(name_pool);

 result_plan->plan_tree_ = logical_plan;


 update_stmt = new(update_stmt) ObUpdateStmt(name_pool);

 query_id = logical_plan->generate_query_id();
 //为update_stmt设置新的标识qid
 update_stmt->set_query_id(query_id);

 logical_plan->add_query(update_stmt);

 ParseNode* table_node = node->children_[0];
 //解析表 
 ret = resolve_table(result_plan, update_stmt, table_node, table_id);

 update_stmt->set_update_table(table_id);

 ParseNode* assign_list = node->children_[1];

 uint64_t ref_id;
 ColumnItem *column_item = NULL;
 //解析要更新的列表,如:update student set sex="M",grade="2" where name = "xiaoming";
 for (int32_t i = 0; ret == OB_SUCCESS && i < assign_list->num_child_; i++)
 {
 ParseNode* assgin_node = assign_list->children_[i];

 /* resolve target column */
 ParseNode* column_node = assgin_node->children_[0];

 ObString column_name;
  column_name.assign_ptr(
  (char*)(column_node->str_value_), 
  static_cast(strlen(column_node->str_value_))
  );
 //1 根据列名获取列
 column_item = update_stmt->get_column_item(NULL, column_name);
 //2 解析列到vector
 ret = update_stmt->add_column_item(*result_plan, column_name, NULL, &column_item);
 //3 增加列引用到update_stmt 
 ret = update_stmt->add_update_column(column_item->column_id_);

  /* resolve new value expression */
 //4 解析值表达式
 ParseNode* expr = assgin_node->children_[1];
 ret = resolve_independ_expr(result_plan, update_stmt, expr, ref_id, T_UPDATE_LIMIT);
 //5 添加值表达式引用到update_stmt
 ret = update_stmt->add_update_expr(ref_id)
 }
 //解析where子句
 ret = resolve_where_clause(result_plan, update_stmt, node->children_[2]);

 return ret;
}

我们仍旧以update语句为例。上面是根据源代码整理的逻辑,不是源码,主要是为了理清思路。

  1. 首先是创建一个新的查询update_stmt,并为其生成一个独立的查询标识qid
  2. 解析语句中的表,并将表的标识tid添加到update_stmt的引用列表
  3. 利用for循环逐个解析要更新的列-值对:
    (1). 根据列名获取列;
    (2). 将该列存储到update_stmtvector中,并将列引用id添加到update_stmt的更新列列表ObArray update_columns_中;
    (3). 解析值表达式;
    (4). 将值表达式引用id添加到更新值列表ObArray update_exprs_中去;
  4. 解析where子句.

3.2 如何解析表和列?

通过上面我们知道,逻辑计划的解析的一个重要内容就是要确定查询stmt,表,列,表达式的标识.查询和表达式的标识id都可以在解析的时候生成。因为这两项不是线程共有的,但是表和列是持久的数据,可以跨线程使用同样的id。这些表和列的信息由谁来管理?

3.2.1 使用Schema

追根溯源,你会发现实体表和列的id是在ob_schema.cpp中获取的。什么是schema?schema就是数据库对象的一个集合。网上有一个很形象的比喻,我稍微做了点改动:

什么是Database,什么是Schema,什么是Table,什么是列,什么是行,什么是User?我们可以可以把Database看作是一个大仓库,仓库分了很多很多的房间,Schema就是其中的房间,一个Schema代表一个房间,Table可以看作是每个Schema中的柜子,行和列就是柜子中的格子。User就是房间的主人。

OceanBase要求schema强类型约束,也就是要预先定义好schema。这样可以方便的进行各种online ddl操作。

OceanBase的表和列信息存储在Schema的一个hash_map中。关于Schema 以后再深入了解。

四、总结

制定逻辑计划,最关键的是要理解逻辑计划的设计目标,其中最主要的内容就是确定逻辑计划中使用到的查询Stmt,表,列,表达式,并为它们生成或设置唯一标识,确保在同一个逻辑计划中是不相同的。制定逻辑计划的函数只要是reslove系列函数。而表和列的信息存储在Schema中一个hash_map中。


欢迎光临我的网站----我的博客园----我的CSDN。
如果阅读本文过程中有任何问题,请联系作者

热心网友 时间:2022-04-12 19:36

这个还是有必要考的,你看看下面的简介吧。
OceanBase数据库是由蚂蚁集团完全自主研发的企业级分布式关系数据库,始创于 2010 年。具有数据强一致、高可用、高性能、在线扩展、高度兼容 SQL 标准和主流关系数据库、低成本等特点。至今已成功应用于支付宝及阿里巴巴全部核心业务。并从 2017 年开始服务于广泛行业客户,包括南京银行、西安银行、天津银行、苏州银行、东莞银行、常熟农商行、广东农信、中国人保等近四十家银行、保险和证券机构,以及印度最大支付公司Paytm。
OBCA (OceanBase 数据库认证专员)认证主要讲解 OceanBase 的发展历程、应用案例、产品架构、核心功能、部署安装等知识。
以下内容是对OBCA在线课程内容进行的整理,与课程大纲一致共分为6个章节。

分布式数据库与集中式数据库的差异
OceanBase数据库产品简介
OceanBase产品家族及基础概念
OceanBase集群技术架构
OB Server的SQL引擎和存储引擎
OCP及ODC工具介绍
OceanBase功能

OceanBase设计和实现的时候暂时摒弃了不紧急的DBMS的功能,例如临时表,视图(view),研发团队把有限的资源集中到关键点上,当前OceanBase主要解决数据更新一致性、高性能的跨表读事务、范围查询、join、数据全量及增量mp、批量数据导入。

OceanBase数据访问特点

虽然数据总量比较大,但跟许多行业一样,淘宝业务一段时间(例如小时或天)内数据的增删改是有限的(通常一天不超过几千万次到几亿次),根据这个特点,OceanBase把一段时间内的增删改等修改操作以增量形式记录下来(称之为动态数据,通常保存在内存中),这样也使得了主体数据在一段时间内保持了相对稳定(称之为基准数据)。

由于动态数据相对较小,通常情况下,OceanBase把它保存在独立的服务器UpdateServer的内存中。以内存保存增删改记录极大地提高了系统写事务的性能。此外,假如每条修改平均消耗100 Bytes,那么10GB内存可以记录100M(即1亿)条修改,且扩充UpdateServer内存即增加了内存中容纳的修改量。不仅如此,由于冻结后的内存表不再修改,它也可以转换成sstable格式并保存到SSD固态盘或磁盘上。转储到SSD固态盘后所占内存即可释放,并仍然可以提供较高性能的读服务,这也缓解了极端情况下UpdateServer的内存需求。为了应对机器故障,动态数据服务器UpdateServer写commit log并采取双机(乃至多机)热备。由于UpdateServer的主备机是同步的,因此备机也可同时提供读服务。

因为基准数据相对稳定,OceanBase把它按照主键(primary key,也称为row key)分段(即tablet)后保存多个副本(一般是3个)到多台机器(ChunkServer)上,避免了单台机器故障导致的服务中断,多个副本也提升了系统服务能力。单个tablet的尺寸可以根据应用数据特点进行配置,相对配置过小的tablet会合并,过大的tablet则会*。

由于tablet按主键分块连续存放,因此OceanBase按主键的范围查询对应着连续的磁盘读,十分高效。

对于已经冻结/转储的动态数据,OceanBase的ChunkServer会在自己不是太繁忙的时候启动基准数据与冻结/转储内存表的合并,并生成新的基准数据。这种合并过程其实是一种范围查询,是一串连续的磁盘读和连续的磁盘写,也是很高效的。

传统DBMS提供了强大的事务性、良好的一致性和很短的查询修改响应时间,但数据规模受到严重制约,缺乏扩展性;现代云计算提供了极大的数据规模、良好的扩展性,但缺乏跨行跨表事务、数据一致性也较弱、查询修改响应时间通常也较长,OceanBase的设计和实现融合了二者的优势:

UpdateServer:类似于DBMS中的DB角色,提供跨行跨表事务和很短的查询修改的响应时间以及良好的一致性。

ChunkServer:类似于云计算中的工作机(如GFS的chunk server),具有数据多副本(通常是3)、中等规模数据粒度(tablet大小约256MB)、自动负载平衡、宕机恢复、机器plug and play等特点,系统容量及性能可随时扩展。

MergeServer:结合ChunkServer和UpdateServer,获得最新数据,实现数据一致性。

RootServer:类似于云计算中的主控机(如GFS master),进行机器故障检测、负载平衡计算、负载迁移调度等。

上述的DBMS和云计算技术的优势互补使得OceanBase既具有传统DBMS的跨行跨表事务、数据的强一致性以及很短的查询修改响应时间,还有云计算的海量数据管理能力、自动故障恢复、自动负载平衡以及良好的扩展性。

OceanBase当前在淘宝的应用

OceanBase现在已经应用于淘宝收藏夹,用于存储淘宝用户收藏条目和具体的商品、店铺信息,每天支持4~5千万的更新操作。等待上线的应用还包括CTU、SNS等,每天更新超过20亿,更新数据量超过2.5TB,并会逐步在淘宝内部推广,也期待外部合作者。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
美的家用电器有哪些 美的系列品牌有哪些 现在微波炉哪个好用 美的微波炉系列有哪些 使命召唤4 用狙击枪的那关 使命召唤4撤离辐射区路怎么走 如何保护听力?你有了解过吗? 汇编语言编程有哪些特点呢? 少年的你经典语录带图片 少年的你易烊千玺台词精选 关于中秋节的日记怎么写 三级数据库证有用吗 小白鞋染上黑色染发剂怎么办? 白鞋子上面染色了怎么办 白色板鞋染上红色的酒精怎么洗掉? 白皮鞋染色怎么去除 xlsx表格卡怎么办? 电脑打开excel文件卡死怎么办 404 Not Found excel文件不大但很卡 一直在用的EXCEL表格最近很卡怎么回事 excel表格编辑很卡怎么解决 注册微信网页无法打开怎么回事? 你好,我登录微信它是显示无法打开网页? 注册微信显示网页无法打开怎么回事? 新手机微信登录为什么打不开网页 为什么微信注册显示网页无法打开? 微信账号密码显示网页无法打开? 手机恢复出厂设置后,登陆微信一直进不去!一直是这个页面,怎么办? 学应用统计学的学生考教师资格证会好就业吗 读经济统计学专业可以当数学老师吗? 计算机四级数据库证含金量高吗 OCP认证有什么用? 三级数据库考了有用吗 数据库系统工程师证书有用吗 考过了计算机三级数据库,有用吗? 怎么申请MCN 如何增加cad的字体 怎么增加cad字体样式 cad怎么添加字体库 CAD2020版怎样添加中文字体? CAD中怎么设置字体 为什么说男人要多吃韭菜,韭菜真能壮阳吗? 韭菜真的可以壮阳吗? 多吃韭菜真的能壮阳吗? 韭菜可以壮阳?女生经常吃韭菜会不会导致胡子长得更快? 韭菜能壮阳吗 经常吃韭菜真的可以“壮阳”吗? 吃韭菜可以壮阳吗? 韭菜可以壮阳吗? 听说吃韭菜可以壮阳?