0


【数据库内核分析系列】:数据库表的创建过程

在数据库中,除了DML之外的所有查询都通过ProcessUtility模块来执行,包括了各类DDL语句、事务相关语句、游标相关语句等。上层调用函数为exec_simple_query函数,其中PortalStart函数和PortalDrop函数部分较为简单。核心函数是PortalRun函数下层调用的standard_ProcessUtility函数,该函数通过switch case语句处理了各种类型的查询语句,包括事务相关查询、游标相关查询、schema相关操作、表空间相关操作、表定义相关操作等。
standard_ProcessUtility函数会根据nodeTag(parsetree)的值来确定sql的操作类型,create table一般都是进入T_CreateStmt分支,调用CreateCommand函数。

voidstandard_ProcessUtility(Node* parse_tree,constchar* query_string, ParamListInfo params,bool is_top_level,
    DestReceiver* dest,#ifdefPGXCbool sent_to_remote,#endif/* PGXC */char* completion_tag,bool isCTAS){
……
    errno_t errorno = EOK;switch(nodeTag(parse_tree)){// 根据nodeTag(parsetree)的值来确定sql的操作类型
……
        case T_CreateStmt:{// create table#ifdefPGXCCreateCommand((CreateStmt*)parse_tree, query_string, params, is_top_level, sent_to_remote, isCTAS);#elseCreateCommand((CreateStmt*)parse_tree, query_string, params, is_top_level, isCTAS);#endif}break;
……

在这里插入图片描述

CreateCommand函数先解析parse_tree获取stmt,如果stmt为空则表明表已经存在。如果stmt不为空对stmts进行遍历,如果是 CreateStmt就调用DefineRelation。AlterTableCreateToastTable判断是否需要创建toast表并创建,AlterCStoreCreateTables判断是否需要创建列存表并创建。

#ifdefPGXCvoidCreateCommand(CreateStmt *parse_tree,constchar*query_string, ParamListInfo params, 
                   bool is_top_level, bool sent_to_remote, bool isCTAS)#elsevoidCreateCommand(CreateStmt *parse_tree,constchar*query_string, ParamListInfo params, bool is_top_level,
    bool isCTAS)#endif{
……
    /* Run parse analysis ... */if(u_sess->attr.attr_sql.enable_parallel_ddl)// 先解析parse_tree获取stmt
        stmts =transformCreateStmt((CreateStmt*)parse_tree, query_string, NIL, true,&namespace_id, is_first_node);else
        stmts =transformCreateStmt((CreateStmt*)parse_tree, query_string, NIL, false,&namespace_id);/*
     * If stmts is NULL, then the table is exists.
     * we need record that for searching the group of table.
     */if(stmts == NIL){// 如果stmt为空则表明表已经存在
        table_is_exist = true;
……
    /* ... and do it */foreach(l, stmts){// 遍历stmts
        Node* stmt =(Node*)lfirst(l);if(IsA(stmt, CreateStmt)){// 如果是 CreateStmt就调用DefineRelation
            Datum toast_options;staticconstchar*const validnsps[]= HEAP_RELOPT_NAMESPACES;/* forbid user to set or change inner options */ForbidOutUsersToSetInnerOptions(((CreateStmt*)stmt)->options);/* Create the table itself */
            rel_oid =DefineRelation((CreateStmt*)stmt,((CreateStmt*)stmt)->relkind == RELKIND_MATVIEW ?
                                                                    RELKIND_MATVIEW : RELKIND_RELATION,
                                    InvalidOid, isCTAS);
……
            AlterTableCreateToastTable(rel_oid, toast_options, AccessShareLock);AlterCStoreCreateTables(rel_oid, toast_options,(CreateStmt*)stmt);AlterDfsCreateTables(rel_oid, toast_options,(CreateStmt*)stmt);AlterCreateChainTables(rel_oid, toast_options,(CreateStmt *)stmt);
……

DefineRelation函数获取到表名relname、名字空间relnamespace、表空间reltablespace、表类型relkind和relpersistence等信息后调用heap_create_with_catalog创建relation。

(gdb) f 0#0  heap_create_with_catalog (relname=0x7fb4fa872140 "t100", relnamespace=2200, reltablespace=0, relid=0, reltypeid=0,reloftypeid=0, ownerid=10, tupdesc=0x7fb4ff2e2e50, cooked_constraints=0x0, relkind=114'r', relpersistence=112'p',
    shared_relation=false, mapped_relation=false, oidislocal=false, oidinhcount=0, oncommit=ONCOMMIT_NOOP,
    reloptions=140415352057720, use_user_acl=true, allow_system_table_mods=false, partTableState=0x0, row_compress=1'\001',
    bucketinfo=0x0, record_dependce=true, ceLst=0x0, storage_type=HEAP_DISK, partLockMode=1) at heap.cpp:2521

heap_create_with_catalog主要完成表物理文件的创建和表元信息注册到系统表中,涉及系统包包括pg_class,pg_attribute,pg_depend,pg_object,pg_type,pg_index和pg_partition。
在这里插入图片描述

其中heap_create内部首先调用了RelationBuildLocalRelation创建RelationData,并加入到relCache,RelationData表示一个表的元信息,这些信息都可以由系统表元组中的信息构造得到。然后根据这些信息通过调用RelalionCreateStorage函数创建物理文件。

附:创建表create table的函数调用栈
#0 RelationCreateStorage
#1 heap_create
#2 heap_create_with_catalog
#3 DefineRelation
#4 CreateCommand
#5 standard_ProcessUtility
#6 gsaudit_ProcessUtility_hook
#7 pgaudit_ProcessUtility
#8 hypo_utility_hook
#9 ProcessUtility
#10 PortalRunUtility
#11 PortalRunMulti
#12 PortalRun
#13 exec_simple_query
#14 PostgresMain

openGauss: 一款高性能、高安全、高可靠的企业级开源关系型数据库。

🍒如果您觉得博主的文章还不错或者有帮助的话,请关注一下博主,如果三连点赞评论收藏就更好啦!谢谢各位大佬给予的支持!

标签: 数据库 sql java

本文转载自: https://blog.csdn.net/GaussDB/article/details/127743832
版权归原作者 Gauss松鼠会 所有, 如有侵权,请联系我们删除。

“【数据库内核分析系列】:数据库表的创建过程”的评论:

还没有评论