-
DWS 已有ntp服务如何修改为chrony服务?
-
一、问题背景:delete语句执行慢,delete几千条数据,执行要用一分钟,不满足要求。DELETE FROM schema_css.t_call_record_attendee WHERE confuuid in ('xxx','xxx','xxx');表结构: Column | Type | Modifiers | Storage | Stats target | Description --------------+-------------------------+------------------------------------+----------+--------------+------------- uuid | character varying(64) | not null | extended | | confuuid | character varying(64) | not null | extended | | orguuid | character varying(128) | | extended | | logicid | character varying(128) | | extended | | roletype | character varying(16) | default 'GUEST'::character varying | extended | | displayname | nvarchar2(512) | | extended | | terminaltype | character varying(32) | | extended | | callnumber | character varying(128) | | extended | | deptname | nvarchar2(512) | | extended | | deptuuid | character varying(128) | | extended | | useruuid | character varying(128) | | extended | | attribute | character varying(4096) | | extended | | updatetime | bigint | default 0 | plain | | createtime | bigint | | plain | | deleted | integer | default 0 | plain | | Indexes: "t_call_record_attendee_pkey" PRIMARY KEY, cbtree (uuid, confuuid) TABLESPACE pg_default "i_t_call_record_attendee_confuuid" cbtree (confuuid) TABLESPACE pg_default "i_t_call_record_attendee_logicid" cbtree (logicid) TABLESPACE pg_default "i_t_call_record_attendee_useruuid" cbtree (useruuid) TABLESPACE pg_defaultHas OIDs: noDistribute By: HASH(confuuid)Location Nodes: ALL DATANODESOptions: orientation=column, enable_hstore_opt=true, enable_binlog=on, binlog_ttl=86400, bucketnums=16384, compression=middle, colversion=2.0, enable_delta=false, enable_hstore=true, enable_turbo_store=true二、问题定位1、无锁冲突,无性能瓶颈,执行的是delete的语句,无法打印执行计划;topsql中记录的是fqs,也没有计划。将delete转化为select语句执行:select * FROM schema_css.t_call_record_attendee WHERE confuuid in ('xxx','xxx','xxx');走FQS执行计划,执行很快;关闭fqs后,走了索引,依然很快,未出现慢的情况。关闭fqs后,打印delete的verbose计划,和select快的计划是一致的,未发现问题。由于FQS计划相当于直连DN执行,因此直连DN打印执行计划,发现也是走了索引的快的计划,性能很快,未能复现。2、根据等待视图,抓取语句堆栈如下:postgres=# select * from pgxc_thread_wait_status where query_id in (select query_id from pgxc_stat_activity where query like '%T_CALL_RECORD_ATTENDEE%' and usename !='Ruby' order by query_start desc limit 1); node_name | db_name | thread_name | query_id | tid | lwtid | ptid | tlevel | smpid | wait_status | wait_event --------------+---------+------------------------+--------------------+-----------------+---------+------+--------+-------+----------------------------------+------------ dn_6003_6004 | mms_db | PostgreSQL JDBC Driver | 145241088536308910 | 139795727430888 | 3127403 | | 0 | 0 | none | dn_6009_6010 | mms_db | PostgreSQL JDBC Driver | 145241088536308910 | 140270667850240 | 4116415 | | 0 | 0 | none | dn_6011_6012 | mms_db | PostgreSQL JDBC Driver | 145241088536308910 | 139655937670760 | 4116416 | | 0 | 0 | none | dn_6001_6002 | mms_db | PostgreSQL JDBC Driver | 145241088536308910 | 139846959760552 | 3127402 | | 0 | 0 | none | dn_6007_6008 | mms_db | PostgreSQL JDBC Driver | 145241088536308910 | 140166692434008 | 370635 | | 0 | 0 | none | dn_6005_6006 | mms_db | PostgreSQL JDBC Driver | 145241088536308910 | 139766594408728 | 370634 | | 0 | 0 | none | cn_5002 | mms_db | PostgreSQL JDBC Driver | 145241088536308910 | 139761117827248 | 2735702 | | 0 | 0 | wait node(total 6): dn_6011_6012 | 3、dn抓堆栈postgres=# SELECT * FROM gs_stack('dn_6001_6002',139846959760552); tid | lwtid | stack -----------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------- 139846959760552 | 3127402 | texteq(FunctionCallInfoData*) + 0x2 | | ExecEvalScalarArrayOp(ScalarArrayOpExprState*, ExprContext*, bool*, ExprDoneCond*) + 0x41c | | ExecQual(List*, ExprContext*, bool) + 0x98 | | ExecResult(ResultState*) + 0x7a | | TupleTableSlot* ExecProcNodeT<false, false, false, false, (NodeTag)201>(PlanState*) + 0x8c | | ExecRowToVecTupleMode(RowToVecState*) + 0x51 | | VectorEngine(PlanState*) + 0x14a | | FetchRows(VecModifyTableState*, EState*, CmdType&, PlanState*, PlanState*, JunkFilter*, RelationData*, void*, tagVecModifyTableFuncSet const*, bool) + 0x245 | | ExecVecModifyTable(VecModifyTableState*) + 0x1ed | | VectorEngine(PlanState*) + 0x14a | | ExecVecToRow(VecToRowState*) + 0xda | | TupleTableSlot* ExecProcNodeT<false, false, false, false, (NodeTag)2000>(PlanState*) + 0x8c | | standard_ExecutorRun(QueryDesc*, ScanDirection, long) + 0x649 | | ExecutorRun(QueryDesc*, ScanDirection, long) + 0x375 | | ProcessQuery(PlannedStmt*, char const*, ParamListInfoData*, _DestReceiver*, char*) + 0xc9 | | PortalRunMulti(PortalData*, bool, _DestReceiver*, _DestReceiver*, char*) + 0x287 | | PortalRun(PortalData*, long, bool, _DestReceiver*, _DestReceiver*, char*, bool) + 0x583 | | exec_execute_message(char const*, long) + 0x342 | | PostgresMain(int, char**, char const*, char const*) + 0x15e4 | | SubPostmasterMain(tag_gs_thread_args*) + 0x1209 | | MainStarterThreadFunc(void*) + 0x3f | | ThreadStarterFunc(void*) + 0x40 | | 0x7f323d8dc67a | | 0x7f323d95f160 | | (1 row)发现堆栈和快的计划对不上,快的计划走了索引,而堆栈中走了全表扫描。4、继续对比复现语句和客户实际业务语句发下,慢的情况是PBE(Prepare-Bind-Execute 预编译)后,参数是通过变量的方式传到条件里的,而复现问题时,条件都是直接写好的。客户的业务语句是通过JDBC绑定变量的方式执行的,形如:DELETE FROM schema_css.t_call_record_attendee WHERE confuuid in ($1, $2, $3);而在复现时,将其中的$1等变量内容替换成了实际常量:DELETE FROM schema_css.t_call_record_attendee WHERE confuuid in (1234, 1235, 1236);怀疑是PBE场景导致的执行计划差异。使用PBE方式直连DN模拟PBE的FQS计划,发现执行计划和抓到的堆栈匹配,问题复现,确认和PBE有关。prepare p1(text,text) as select * FROM schema_css.t_call_record_attendee a WHERE confuuid in( $1, $2);explain verbose execute p1('SFyuC4xX3X7yQHzXqAQxv8md3MHgfoWq','MUZASKbhpDBQwK1A2faPpRzw58qRvV2Z');关闭FQS后,在CN上执行,生成了索引计划,执行性能较快,因此可将关闭FQS作为规避方案set enable_fast_query_shipping=off;prepare p1(text,text) as select * FROM schema_css.t_call_record_attendee a WHERE confuuid in( $1, $2);explain verbose execute p1('SFyuC4xX3X7yQHzXqAQxv8md3MHgfoWq','MUZASKbhpDBQwK1A2faPpRzw58qRvV2Z');5、用户级修改参数alter user xxx set enable_fast_query_shipping=off;中间有一个小插曲是,用户级修改参数后,新建连接立即生效,不需要重启,但是老连接不生效,因此需要用户新建连接测试规避方案是否有效。可以通过审计日志查看用户登入登出时间,确保在参数调整后新建连接:select * from pgxc_query_audit('2025-08-15 00:00:00','2025-08-15 06:30:00') where session_id like '%对应的pid%' and detail_info not in ('START TRANSACTION','ROLLBACK','COMMIT') and operation_type ='login_logout' order by begintime;修改参数生效后,验证问题得到解决。 三、问题根因通过PBE的方式执行,array用法在PBE场景下不支持向量化,in条件会被转化为array,直接执行时,走的FQS计划,导致走了全表扫描,再走行存过滤表达式,性能差。关闭FQS后,变量在CN上被替换,替换后支持向量化,因此可以生成索引扫描计划,性能快。规避方法:(1)通过hint关闭fqs : /*+ set global(enable_fast_query_shipping off) */,仅影响当前语句(2)用户级关闭参数: alter user xxx set enable_fast_query_shipping=off; 仅影响当前用户,一般不会产生其他副作用
-
云计算未来发展趋势大家怎么看
-
GaussDB(DWS)的技术优势cid:link_0声明式查询语言cid:link_8单个未索引属性cid:link_1多属性过滤cid:link_2MPP的分布式数据仓库cid:link_3逻辑集群架构cid:link_9逻辑集群的隔离性cid:link_10物理集群cid:link_4逻辑集群用户cid:link_11非逻辑集群用户cid:link_12逻辑集群的使用场景cid:link_5逻辑集群下SQL语法和兼容性cid:link_6TopSQL相关视图与GUC参数cid:link_7RESOURCE资源cid:link_13TopSQL视图字段https://bbs.huaweicloud.com/forum/thread-0228191133868088068-1-1.html
-
因数据量变化,导致作业执行时间增加,可以分析A2/B1/D1/G1,进而确认作业查询的数据表是否有明显的数据量增加;由于目前历史TopSQL视图字段信息较多,建议使用PGXC_QUERY_INFO视图查看查询经典字段信息,无需手动过滤无关字段。因其它并发作业抢占,导致作业排队,从而导致作业执行时间增加,可以分析A1/B1/D1,进而查看作业执行的同时期是否有大量并发作业在执行;因其它作业而产生的CPU抢占,导致作业执行时间增加,可以分析A2/D1/E1,进而查看作业执行的同时期是否有大量并发作业在执行;因其它作业而产生的IO抢占,导致作业执行时间增加,可以分析A2/F1,进而查看作业执行的同时期是否有大量并发作业在执行;禁止某一类语句执行,可参考H1。值得注意的是,发生资源争抢时,可能会出现并发症,即CPU、IO抢占,作业排队现象都会发生,针对并发症问题,可以逐步分析解决,比如:第一步,调整作业执行顺序,减少并发作业数量,减少阻塞时间;第二步,定位出同时段执行的典型计算密集型、存储密集型作业,先移动到其它时间段执行,减少对本作业的影响;第三步,在无其他作业明显干预的情况下,做进一步分析。
-
RESOURCE_TRACK_COST(0)设置对当前会话的语句进行资源监控的最小执行代价。RESOURCE_TRACK_LEVEL(QUERY)设置当前会话的资源监控的等级,默认为query级别。RESOURCE_TRACK_APPLICATION设置TopSQL记录指定客户端下发的语句,目前支持设置的客户端为:gs_rewind、cm_agent、pgxc_clean、gs_clean、gs_running_xacts、OM、wlm。设置多个客户端时,相邻的值需用英文逗号隔开TOPSQL_RETENTION_TIME(30)历史TopSQL中GS_WLM_SESSION_INFO和GS_WLM_OPERATOR_INFO表中数据的保存时间,单位为天(历史TopSQL视图的数据实际是存储在postgres数据库中的dbms_om.gs_wlm_session_info系统表上,该表通过start_time进行分区,每天一个分区,通过参数topsql_retention_time配置默认保留30个分区即30天的记录,定期对pgxc_wlm_session_info的分区进行清理、创建,hash分布且分布键为queryid。如判断该表占用空间较多,可调低该参数,最多30min后表空间可下降)。SESSION_HISTORY_MEMORY(100MB)设置历史查询视图的内存大小,如果语句运行过程中出现"TopSQL lfq is full, failed to save queryid"报错信息,可通过如下SQL查询TopSQL无锁队列总共的内存和已使用的内存。
-
在实际的生产环境中,难免会出现一些突发情况,如计划跳变、异常中断、作业长时间执行不结束等,如果已经没有现场,而且也没有工具将当时的作业运行情况记录下来的话,那么事后就要投入更多的人力以及时间成本对错误进行定位和解决,有时还往往定位不到错误出现的地方。为了解决这种情况,GaussDB(DWS)开发了TopSQL功能,对运行中的语句记录(实时TopSQL),对运行完成的语句进行记录(历史TopSQL)。 目前TopSQL功能被用户广泛使用,是性能定位、劣化分析、审计回溯等重要的基石,为用户提供覆盖内存、耗时、IO、网络、空间等多方面的监控能力。 TopSQL可以帮助用户实现下列功能:①确定影响数据库性能的资源最密集的SQL查询;②监控和跟踪SQL查询随时间推移的性能变化;③分析查询执行计划以确定潜在的优化。TopSQL功能默认打开(use_workload_manager,enable_resource_track,enable_resource_record参数均默认为on),GUC参数详细介绍如下:use_workload_manager(on)资源管理总开关,TopSQL功能开启该参数需要为on。enable_resource_track(on)是否开启监控功能,实时TopSQL的总开关,关闭之后实时TopSQL将不再进行记录,更不会在历史TopSQL中出现。enable_resource_record(on)设置是否开启资源监控记录归档功能。开启时,对于执行结束的记录,会分别被归档到相应的INFO视图,CN和DN都需要设置上。enable_track_record_subsql(on)控制是否记录存储过程、匿名块内部语句(默认为on)(建议820及以上版本开启,TopSQL记录该子语句的前提是:子语句下推到DN执行;子语句执行时间超过resource_track_subsql_duration,目前TopSQL只能记录第一层循环的子语句,多层嵌套循环的子语句不会记录)。resource_track_duration(60s)设置实时TopSQL中记录的语句执行结束后进行历史信息转存的最小执行时间,该时间记录值的判断是包含了排队时间和运行时间(如果在解析优化阶段发生了锁等待,产生的时间不会记录到该参数中),当排队时间+运行时间 > RESOURCE_TRACK_DURATION时,TopSQL历史视图会记录作业信息。CPU和存储资源充足的场景建议设置为0,可记录更全的业务;在QPS高于100场景,可酌情调大,如1-10s。
-
系统管理员创建表时如果没有指定TO GROUP,创建的表默认在集群中第一个创建的逻辑集群(pgxc_group中oid最小的逻辑集群)中;通过GUC 参数default_storage_nodegroup可以改变默认的逻辑集群名称;逻辑集群下,所有表(外表)都只分布在所属逻辑集群的DN节点上。逻辑集群下,创建的函数中不能使用%type 引用表字段类型;逻辑集群下,如果函数的参数和返回值有表类型,这些表必须属于同一个逻辑集群;逻辑集群下,对外表来说,CREATE TABLE … LIKE 语句中源表和目的表需要在同一个逻辑集群;逻辑集群下,创建表时如果需要和其他表共享Sequence,该Sequence需要是所有DN节点共享的;逻辑集群下,如果函数中涉及多个逻辑集群表操作,该函数不应该声明为IMMUTABLE类型和SHIPPABLE类型,如果这样声明,会导致函数可能被下推到DN执行,这样执行过程中DN会找不到不属于其逻辑集群的表;如果函数中包含更新操作,不能声明成IMMUTABLE类型和STABLE类型;逻辑集群下需要考虑逻辑集群权限,如果SQL语句或函数体中如果涉及属于不同逻辑集群的表,SQL语句和函数的执行用户需要授予这些逻辑集群的USAGE权限。
-
多子业务拆分:将一个大业务拆分为多个子业务,每个子业务创建一个独立逻辑集群;子业务之间资源隔离,同时也可以方便地进行跨子业务查询。例如:将需要大批量查询的数据(比如跑批数据)部署在一个逻辑集群中;将需要实时查询的数据部署在一个逻辑集群;将需要频繁更新的数据部署在一个逻辑集群;其他特定资源要求的逻辑集群。逻辑集群有三种创建方式:在新安装的全新的集群上划分逻辑集群,要求:新安装的物理集群没有任何用户表、多租户或资源池;全新的集群包含DN1~DN6 6个节点, 我们将DN1~DN3用来创建逻辑集群NodeGroup1, 剩下未使用的DN4~DN6暂时将放入弹性池中, 后续可以用来创建新的逻辑集群。将需要拆分到不同逻辑集群的表通过Insert into …select迁移到其他逻辑集群,并删除原表;原逻辑集群可以通过缩容释放部分节点(但被释放的节点必须独立成环);逻辑集群用户执行CREATE TABLE创建的表,分布在所属逻辑集群包含的DN节点上;系统管理员在指定逻辑集群上创建表,需要通过TO GROUP指定逻辑集群名称。
-
非逻辑集群用户:在逻辑集群模式下,没有绑定任何逻辑集群的普通用户,这些用户无法创建任何表;逻辑集群转换:将整个集群从非逻辑集群模式转换成逻辑集群模式,物理集群中所有DN节点都被划分到一个统一的逻辑集群中,所有创建了表和资源池的用户都被绑定到该逻辑集群,所有表都属于该逻辑集群,同时创建一个空的弹性集群;逻辑集群回退:将整个集群从逻辑集群模式转换成非逻辑集群模式,只有在集群中只有一个逻辑集群(该逻辑集群包含所有DN节点),且弹性集群为空的时候才允许,转换后所有逻辑集群都会删除,弹性集群也会删除;集群公共组件:指被多个逻辑集群共享的组件,包括CN, GTM, cmserver,cmagent, ETCD;数据库公共对象:指除了表、外表之外的数据库对象;这些对象是所有逻辑集群共享的(但仍然有特殊函数,sequence是特定逻辑集群私有的);初始逻辑集群:指第一个创建的逻辑集群,在没有明确指定逻辑集群名称时,系统管理员创建的表会在初始逻辑集群中。
-
资源池(Resource Pool):用来进行资源配置的数据库对象;可以用来配置CPU,内存资源;在逻辑集群模式下,创建资源池必须指定逻辑集群名称;控制组(Control Group):通过cgroup来配置CPU资源,资源池通过指定的控制组来限制用户的CPU资源;GaussDB通过gs_cgroup工具来配置控制组;多租户:基于资源池的租户资源管理,包含组资源池和业务资源池两级。数据库用户通过和业务资源池绑定来控制用户执行作业时的资源;系统管理员:在没开启权限分离前基本等同于超级用户,拥有对数据库管理的所有权限;逻辑集群管理员:仅仅属于某个逻辑集群的管理员,但本质上还是一个普通用户,但是可以将所属逻辑集群的访问权限授予其他用户,可以在所属逻辑集群内创建资源池;逻辑集群用户:在逻辑集群模式下,绑定到某个逻辑集群的普通用户,只有绑定到逻辑集群后,才能在该逻辑集群下创建用户表;
-
物理集群:有时候也叫大集群,是实际安装的GaussDB分布式数据库集群。包含所有物理节点,所有CN,DN,GTM,CM,ETCD等组件在内。NodeGroup:也叫节点组,是将部分DN节点组成一个逻辑组,可以在一个NodeGroup上创建表;普通的NodeGroup非常灵活,对包含的DN节点没有任何限制,允许一个DN同时属于多个NodeGroup。逻辑集群:是一种特殊的NodeGroup,要求所包含的DN节点以及DN节点所在物理节点都只能属于一个逻辑集群。弹性集群:是一种特殊的NodeGroup,只在逻辑集群模式下存在,第一次创建逻辑集群时自动创建,可能包含DN节点,也可能不包含任何DN节点;Installation nodegroup:GaussDB安装时自动创建的NodeGroup,包含物理集群内所有DN节点;名称通常是group_version1, group_version2;逻辑集群模式:全新安装的数据库集群总是非逻辑集群模式,当数据库集群中成功创建了一个逻辑集群后,就自动转换为逻辑集群模式,判断是否在逻辑集群模式可以通过检查弹性集群是否存在来判断;当删除弹性集群后,数据库集群就转换回非逻辑集群模式(只有所有逻辑集群都删除后,才能删除弹性集群)。
-
使用逻辑集群比单纯用多租户的资源隔离性好,比采用多套物理集群的业务数据互访能力强,但缺点是不同业务不能独立运维。下面将具体来看下逻辑集群对数据隔离,资源隔离,权限隔离的处理。逻辑集群的数据隔离是指用户表数据的隔离。逻辑集群的系统表信息是共享的(每个逻辑集群都可以看到物理集群中所有的数据库对象,包括表名、视图、函数、存储过程、用户信息、资源池信息)。逻辑集群的资源隔离是指不同逻辑集群访问本逻辑集群内数据时CPU,内存,IO资源不存在资源征用。每个逻辑集群内部可以按租户配置资源;逻辑集群访问其他逻辑集群时资源受限;逻辑集群的资源池可以配置并发作业数,CPU(配额和限额),内存,IO资源。每个逻辑集群用户默认只能访问本逻辑集群的表;如果访问其他逻辑集群的表,需要有该逻辑集群的USAGE权限;每个逻辑集群用户只能在本逻辑集群内创建表,不允许在其他逻辑集群创建表;用户创建的所有数据库对象都受到用户所在逻辑集群的权限限制。
-
逻辑集群实现了一个大集群按节点拆分为不同的节点组(NodeGroup),每个节点组构建一个逻辑集群。例如下图中, 将数据节点1与数据节点2构成一个逻辑集群NodeGroup1, 我们可以让部分独立业务的表均分布在NodeGroup1中, 其他业务存放于NodeGroup2中. 逻辑集群可以很好的解决上面所述的问题。企业可以根据不同业务的数据规模为其创建不同节点数的逻辑集群,由于不同节点属于不同的逻辑集群,这样可以做到不同业务之间物理资源彻底隔离。在一个逻辑集群内部,所有节点是对等的,数据保持均衡,确保逻辑集群内部作业高效运行。同时,由于所有业务仍然在一个统一的大集群内,有统一的元数据管理和节点管理,跨逻辑集群数据互访非常容易和高效,这样就可以做到高内聚,低耦合。逻辑集群支持的功能数据按节点隔离逻辑集群间资源(CPU/MEMORY/IO)隔离跨逻辑集群访问资源限制逻辑集群并发控制和内存自适应跨逻辑集群访问权限控制非逻辑集群模式和逻辑集群模式转换(仅限单nodegroup )逻辑集群创建、删除、扩容、缩容、节点替换;逻辑集群GUC参数配置;逻辑集群重启和状态查询;逻辑集群支持弹性计算;
-
传统的基于MPP的分布式数据仓库采用的是全对等架构,每个表数据平均分布到所有节点中,这样能保证足够的并发度以及节点间协同,保证性能SLA。只要保证数据在所有节点上是均衡的,数据查询会将计算平均分配到所有节点上,结构简单,扩展性好 。随着业务越来越大,这种简单的数据分布方式可能会带来一些问题。具体表现为:用户不断把各种业务数据集成到一个数仓中,不同业务逻辑访问同一个数仓,这减少了维护多个数仓的成本,运维方便。但也会导致数仓的数据规模越来越大,表越来越多。不同业务访问数仓过程中会带来资源的竞争,比如CPU、内存、磁盘IO、网络的竞争。虽然通过配置资源池可以一定程度解决资源竞争,但所有业务执行逻辑仍然同时在每个节点上执行,无法做到资源完全隔离。事实上,同一业务的不同作业总是倾向访问本业务相关的表,对其他业务的表访问较少,如果能做到业务内数据“高内聚”,业务间“低耦合”无疑是更好的选择。数据库表无论大小都被切分到所有节点,对小表来说,数据过于分散。当节点规模达到一定程度后,通过增加更多节点,提高查询并行度的方式可能就无法带来理想的扩展性了。如果为了避免集群变大,将不同业务数据拆分成独立集群,集群间数据互访就需要从应用层解决,或者需要跨集群导数。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签