当前位置: 首页 > news >正文

Oracle 19c OCM讲义课程:应用SQL执行计划基线的案例

使用SQL执行计划基线可以保证SQL的性能不下降,但实际生产中默认没有开启,这里是姚远老师在给OCM的学员授课中关于SQL执行计划基线的一个案例,大家可以借鉴一下。
在这里插入图片描述

关于号主,姚远:

  • Oracle ACE(Oracle和MySQL数据库方向)
  • 华为云最有价值专家
  • 《MySQL 8.0运维与优化》的作者
  • 拥有 Oracle 10g、12c和19c OCM等数十项数据库认证
  • 曾任IBM公司数据库部门经理
  • 20+年DBA经验,服务2万+客户
  • 精通C和Java,发明两项计算机专利

修改配置,采集SQL执行计划基线

Oracle 19c与SQL执行计划基线相关的默认参数值如下:

SQL> show parameter baseline
​
NAME             TYPE   VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean   FALSE
optimizer_use_sql_plan_baselines     boolean   TRUE
​

修改后的参数存放在视图DBA_SQL_MANAGEMENT_CONFIG中,检查一下:

COL PARAMETER_NAME FORMAT a32
COL PARAMETER_VALUE FORMAT a32
​
SELECT PARAMETER_NAME, PARAMETER_VALUE FROM   DBA_SQL_MANAGEMENT_CONFIG ;
​
PARAMETER_NAME       PARAMETER_VALUE
-------------------------------- --------------------------------
AUTO_CAPTURE_ACTION
AUTO_CAPTURE_MODULE
AUTO_CAPTURE_PARSING_SCHEMA_NAME parsing_schema IN (TPCC)
AUTO_CAPTURE_SQL_TEXT
AUTO_SPM_EVOLVE_TASK     OFF
AUTO_SPM_EVOLVE_TASK_INTERVAL   3600  -- 
AUTO_SPM_EVOLVE_TASK_MAX_RUNTIME 1800
PLAN_RETENTION_WEEKS     53  -- 53不用的计划会被清理
SPACE_BUDGET_PERCENT     10  -- 占用SYSAUX的空间不超过10%,超过在alert中报警
​
9 rows selected.
​

查看SQL执行计划基线的应用

先将一个索引改成不可见:

SQL> alter index tpcc.CUSTOMER_I1 invisible;
​
Index altered.

应用运行一段时间后,检查已经创建的SQL基线:

SQL> select count(distinct sql_handle),count(distinct plan_name),count(distinct SIGNATURE) from DBA_SQL_PLAN_BASELINES;
​
COUNT(DISTINCTSQL_HANDLE) COUNT(DISTINCTPLAN_NAME) COUNT(DISTINCTSIGNATURE)
------------------------- ------------------------ ------------------------30      30       30
​

可以看到为30个SQL建立了基线,都是ACCEPTED,因为每个SQL只有一个执行计划。

检查与这个索引相关的SQL的执行情况:

SQL> select SQL_ID,EXECUTIONS,OPTIMIZER_COST,SQL_PLAN_BASELINE from v$sql where sql_id='arykx3hpq9xsa';
​
​
SQL_ID        EXECUTIONS OPTIMIZER_COST SQL_PLAN_BASELINE
------------- ---------- -------------- ------------------------------
arykx3hpq9xsa      5102     1945 SQL_PLAN_2v1cfx8jds3vt3a6ea7ea
​

可以看到它用到了一个SQL基线的执行计划,成本是1945,查看这个SQL基线的执行计划:

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE('SQL_2d858eea22dc0f79','SQL_PLAN_2v1cfx8jds3vt3a6ea7ea','basic') );
​
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL handle: SQL_2d858eea22dc0f79
SQL text: UPDATE CUSTOMER SET C_BALANCE = C_BALANCE + :B1 WHERE C_W_ID = :B4AND C_D_ID = :B3 AND C_ID = :B2
--------------------------------------------------------------------------------
​
--------------------------------------------------------------------------------
Plan name: SQL_PLAN_2v1cfx8jds3vt3a6ea7ea    Plan id: 980330474
Enabled: YES   Fixed: NO  Accepted: YES    Origin: AUTO-CAPTURE
Plan rows: From dictionary
--------------------------------------------------------------------------------
​
Plan hash value: 3529770744
​
----------------------------------------
| Id  | Operation   | Name        |
----------------------------------------
|   0 | UPDATE STATEMENT |         |
|   1 |  UPDATE    | CUSTOMER    |
|   2 |   INDEX SKIP SCAN| CUSTOMER_I2 |
----------------------------------------
​
22 rows selected.
​

可以看到这个SQL执行中使用了CUSTOMER_I2 索引,没有使用CUSTOMER_I1索引,因为CUSTOMER_I1这个索引被修改成了不可见。这种检查SQL执行计划的方法和在游标中查询SQL执行计划的方法得到同样的结果:

set pagesize 200
SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('arykx3hpq9xsa'));

将这个索引改成可见:

alter index tpcc.CUSTOMER_I1 visible;

第二次执行应用程序,然后再检查这个SQL的执行情况:

SQL>  select SQL_ID,EXECUTIONS,OPTIMIZER_COST,SQL_PLAN_BASELINE from v$sql where sql_id='arykx3hpq9xsa';
​
SQL_ID        EXECUTIONS OPTIMIZER_COST SQL_PLAN_BASELINE
------------- ---------- -------------- ------------------------------
arykx3hpq9xsa      2376     1945 SQL_PLAN_2v1cfx8jds3vt3a6ea7ea
​

发现这个SQL的执行成本和使用执行计划基线仍然没有发生变化,检查这个SQL对应的执行计划基线:

col plan_name form a30
col signature forma 99999999999999999999999
select sql_handle,plan_name,signature,accepted,optimizer_cost  from DBA_SQL_PLAN_BASELINES 
where SIGNATURE=(select EXACT_MATCHING_SIGNATURE from v$sql where sql_id='arykx3hpq9xsa');
​
SQL_HANDLE           PLAN_NAME             SIGNATURE ACC OPTIMIZER_COST
------------------------------ ------------------------------ ------------------------ --- --------------
SQL_2d858eea22dc0f79         SQL_PLAN_2v1cfx8jds3vt341d91fc     3280185039867613049 NO    3
SQL_2d858eea22dc0f79         SQL_PLAN_2v1cfx8jds3vt3a6ea7ea     3280185039867613049 YES       1945
​

发现这个SQL对应了两个基线,期中成本小到3的基线居然是没有被接受的!
在这里插入图片描述

手工进化基线

因为SQL基线的进化任务要到晚上维护窗口时才会执行,新的基线没有进化成可接受的,所以SQL执行时不会选择这个基线,我们可以手工对这个SQL基线进行进化:

VARIABLE cnt NUMBER
VARIABLE tk_name VARCHAR2(50)
VARIABLE exe_name VARCHAR2(50)
VARIABLE evol_out CLOB
​
begin:tk_name := DBMS_SPM.CREATE_EVOLVE_TASK(sql_handle => 'SQL_2d858eea22dc0f79',  plan_name  => 'SQL_PLAN_2v1cfx8jds3vt341d91fc');
end;
/SELECT :tk_name FROM DUAL;
SQL> SELECT :tk_name FROM DUAL;
​
:TK_NAME
-----------------------
TASK_1551
​
EXECUTE :exe_name :=DBMS_SPM.EXECUTE_EVOLVE_TASK(task_name=>:tk_name); 
SELECT :exe_name FROM DUAL;
:EXE_NAME
--------------------------------
EXEC_3452
​

检查这个进化计划的执行报告:

EXECUTE :evol_out := DBMS_SPM.REPORT_EVOLVE_TASK( task_name=>:tk_name, execution_name=>:exe_name );
SELECT :evol_out FROM DUAL;
SQL> SELECT :evol_out FROM DUAL;
​
:EVOL_OUT
--------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
----------------------------------------------------
​Task Information:---------------------------------------------Task Name        : TASK_1551
​Task Owner        : SYSExecution Name       : EXEC_3452Execution Type       : SPM EVOLVEScope          : COMPREHENSIVE
​Status         : COMPLETEDStarted        : 09/08/2023 15:21:50Finished        : 09/08/2023 15:21:50Last Updated        : 09/08/2023 15:21:50Global Time Limit    : 2147483646Per-Plan Time Limit  : UNUSEDNumber of Errors     : 0
-----------------------------------------
SUMMARY SECTION
--------------------------------------------------
7  Number of plans processed  : 1Number of findings       : 1Number of recommendations  : 1Number of errors       : 0
--------------------------------------------------------
-------------------------------------
​
DETAILS SECTION
---------------------------------------------
----------------------------------------
--------Object ID      : 2
​Test Plan Name     : SQL_PLAN_2v1cfx8jds3vt341d91fcBase Plan Name     : SQL_PLAN_2v1cfx8jds3vt3a6ea7eaSQL Handle      : SQL_2d858eea22dc0f79
​Parsing Schema     : TPCC
​Test Plan Creator  : SYS
​SQL Text      : UPDATE CUSTOMER SET C_BALANCE = C_BALANCE + :B1 WHEREC_W_ID = :B4 AND C_D_ID= :B3 AND C_ID = :B2
​
Bind Variables:
-----------------------------2  -  (NUMBER):  3
​3  -  (NUMBER):  1
​4  -  (NUMBER):  2285
​
​
Execution Statistics:
-----------------------------Base PlanTest Plan--------------------
--------  ----------------------------Elapsed Time (s):  .00064    .000002CPU Time (s):      .000638    .000002Buffer Gets:      117    0Optimizer Cost:    1945    3Disk Reads:      0    0Direct Writes:     0    0Rows Processed:    0    0Executions:      10    10
​
​
FINDINGS SECTION
-----------------------------------------
Findings (1):
-----------------------------1. The plan was verified in 0.12000 seconds. It passed the benefit criterionbecause its verified performance was 390.90001 times better than that ofthe baseline plan.
​
Recommendation:
-----------------------------Consider accepting the plan. Execute
​dbms_spm.accept_sql_plan_baseline(task_name => 'TASK_1551', object_id => 2,task_owner => 'SYS');
​
EXPLAIN PLANS SECTION
---------------------------------------------
​
Baseline Plan
-----------------------------Plan Id    : 9217Plan Hash Value  : 980330474
​
-------------------------------------------
| Id  | Operation     | Name   | Rows | Bytes | Cost | Time     |
---------------------------------------------------
------------------------
|   0 | UPDATE STATEMENT   |     |    1 |    15 | 1945 | 00:00:01 |
|   1 |   UPDATE     | CUSTOMER   |  |  |    |         |
| * 2 |    INDEX SKIP SCAN | CUSTOMER_I2 |   1 |    15 | 1944 | 00:00:01 |
-----------------------------------------------
​
Predicate Information (identified by operation id)
:
------------------------------------------
* 2 - access("C_W_ID"=:B4 AND "C_D_ID"=:B3 AND "C_ID"=:B2)
* 2 - filter("C_ID"=:B2 AND "C_W_ID"=:B4 AND "C_D_ID"=:B3)
​
​
Test Plan
-----------------------------Plan Id    : 9218Plan Hash Value  : 874353148
​
----------------------------------------------------
| Id  | Operation       | Name     | Rows | Bytes | Cost | Time     |
--------------------------------------------------------
|   0 | UPDATE STATEMENT     |       |  1 |    15|    3 | 00:00:01 |
|   1 |   UPDATE       | CUSTOMER   |    |    |   |      |
| * 2 |    INDEX UNIQUE SCAN | CUSTOMER_I1 |    1 |    15 |    2 | 00:00:01 |
--------------------------------------------
​
Predicate Information (identified by operation id):
------------------------------------------
* 2 - access("C_W_ID"=:B4 AND "C_D_ID"=:B3 AND "C_ID"=:B2)
​
--------------------------------------------------
​
​

根据报告中的建议,执行下面的SQL接受第二个基线:

SQL> exec dbms_spm.accept_sql_plan_baseline(task_name => 'TASK_1551', object_id => 2, task_owner => 'SYS');
​
PL/SQL procedure successfully completed.
​

再次检查这个SQL对应的执行计划基线:

col plan_name form a30
col signature forma 99999999999999999999999
select sql_handle,plan_name,signature,accepted,optimizer_cost  from DBA_SQL_PLAN_BASELINES2  where SIGNATURE=(select EXACT_MATCHING_SIGNATURE from v$sql where sql_id='arykx3hpq9xsa');
​
SQL_HANDLE           PLAN_NAME             SIGNATURE ACC OPTIMIZER_COST
------------------------------ ------------------------------ ------------------------ --- --------------
SQL_2d858eea22dc0f79         SQL_PLAN_2v1cfx8jds3vt341d91fc     3280185039867613049 YES    3
SQL_2d858eea22dc0f79         SQL_PLAN_2v1cfx8jds3vt3a6ea7ea     3280185039867613049 YES       1945
​

发现两个基线都是接受的。

第三次执行应用后,然后检查SQL的执行情况:

SQL> select SQL_ID,EXECUTIONS,OPTIMIZER_COST,SQL_PLAN_BASELINE from v$sql where sql_id='arykx3hpq9xsa';
​
SQL_ID        EXECUTIONS OPTIMIZER_COST SQL_PLAN_BASELINE
------------- ---------- -------------- ------------------------------
arykx3hpq9xsa      6849        3 SQL_PLAN_2v1cfx8jds3vt341d91fc
​

发现应用的SQL采用了第二个基线,执行成本从1945降低到3。

删除SQL基线

使用dbms_spm.drop_sql_plan_baseline可以删除SQL基线,但不能一次删除所有的SQL基线,如果要删除所有的SQL基线,需要用游标进行循环删除 ,相关程序如下(参见Doc ID 790039.1)

declare
pgn number;
sqlhdl varchar2(30);
cursor hdl_cur is
select distinct sql_handle from dba_sql_plan_baselines;
begin
open hdl_cur;
loop
fetch hdl_cur into sqlhdl;
exit when hdl_cur%NOTFOUND;
pgn := dbms_spm.drop_sql_plan_baseline(sql_handle=>sqlhdl);
end loop;
close hdl_cur;
commit;
end;/
​
PL/SQL procedure successfully completed.
​
SQL> select count(*) from dba_sql_plan_baselines;
​COUNT(*)
----------0
​

​# 欢迎加我的微信,拉你进数据库微信群👇

相关文章:

Oracle 19c OCM讲义课程:应用SQL执行计划基线的案例

使用SQL执行计划基线可以保证SQL的性能不下降,但实际生产中默认没有开启,这里是姚远老师在给OCM的学员授课中关于SQL执行计划基线的一个案例,大家可以借鉴一下。 关于号主,姚远: Oracle ACE(Oracle和MyS…...

什么是 EDI 857?

EDI 857 的中文含义是装运和账单通知,主要用于供应商传递装运信息和提供采购发票。一个 EDI 857 需要包含与某个具体订单相关联的必要的装运和发票信息,主要包含的业务信息如下: 采购订单编号供应商和买方联系信息产品数量、价格以及诸如 UP…...

OJ项目【登录】——验证码、失败登录多次账户冻结、用户密码加密,我是如何实现的?

目录 前言 1、验证码 1.1、引入pom 1.2、前端核心代码 1.3、后端核心代码 2、账户冻结 2.1、思路: 2.2、核心代码示例: 3、密码加密——加盐算法 3.1、思路: 3.2、代码实现示例: 4、小结:展示我的项目 4…...

js鼠标点击添加图标并获取图标的坐标值

给这个图片添加摄像头图标,并获取图标的坐标值,也就是图标的css样式是positon:absolute,获取left和top的值。 图片1 思路是这样的,获取这里的长度, 图片2 1.鼠标点击时距浏览器的左边距离和上边距离,相当于(0,0)坐标 …...

How to add a jar to a project in eclipse?

Project -> Properties -> Java Build Path -> Libraries -> Add External JARs...

动手实现H5仿原生app前进后退切换效果

动手实现H5仿原生app前进后退切换效果 前言 最近在优化H5页面&#xff0c;我注意到当开发完成的移动端H5页面嵌入到微信小程序或者原生app中时&#xff0c;当触发页面路由切换会与原生app看上去有点格格不入&#xff0c;因为H5页面<router-view>切换路由时是直接替换了…...

【标准化封装 SOT系列 】 D SOT-323 SOT-363

〇、关键词 SC70 。 一、D部分 SOT-323 SOT-363 这个应该叫SC-70可能更合适&#xff0c;典型特征 pin 间距 0.65mm ; body size 2.0mm1.25mm 这一节很像SOT-23&#xff0c;即A部分&#xff0c;因此也是最容易被混淆的。 二、SC70-3 / -5/ -6 鉴于此&#xff0c;封装最好给…...

软件测试肖sir__python之ui自动化实战和讲解03

python之ui自动化实战和讲解...

Kafka序列化反序列化解析、kafka schema

Kafka序列化反序列化解析、kafka schema。 kafka有自己的rpc协议,即nio bytebuf中的数据格式,详见之前的kafka相关介绍的文章。这里我们来看一下大家常用,有时又疑惑的序列化反序列化,对应rpc协议中的records,kafka叫Serdes,实际上也是字面上的意思serialize and deseri…...

谷歌浏览器中如何审查隐藏的元素

谷歌浏览器中如何审查隐藏的元素 方法1&#xff1a; 打开控制台 先鼠标移上先显示出来 快捷键按 CtrlShiftC&#xff0c;只能简单查看宽高&#xff0c;做不到复杂的的样式查询 方法2&#xff1a; 在控制台输入一个以下代码, 并保留光标在控制台闪烁&#xff0c;鼠标移上去显示…...

【vue】使用less报错:显示this.getOptions is not a function

在vue-cli中使用 lang“less” 时报错&#xff1a; Module build failed: TypeError: this.getOptions is not a function at Object.lessLoader 原因&#xff1a;版本过高所致&#xff0c;所用版本为 解决&#xff1a;降低版本&#xff1a;npm install less-loader4.1.0 --s…...

代码随想录第48天 | ● 739. 每日温度 ● 496.下一个更大元素 I

739. 每日温度 /*** param {number[]} temperatures* return {number[]}*/ var dailyTemperatures function(temperatures) {const ntemperatures.lengthconst resArray(n).fill(0)const stack[] // 递增栈&#xff1a;用于存储元素右面第一个比他大的元素下标stack.push(0…...

团购页面.

<!DOCTYPE html> <html><head><title>团购</title><meta http-equiv"content-type" content"text/html; charsetutf-8"/><meta name"apple-mobile-web-app-capable" content"yes"/><lin…...

linux-系统日志/var/log/简介

日志在排查文件的时候至关重要&#xff0c;在Linux上一般跟系统相关的日志默认都会放到/var/log下面。 1、/var/log/boot.log 一般包含系统启动时的日志&#xff0c;包括自启动的服务。 2、/var/log/btmp 记录所有失败登录信息。非文本文件&#xff0c;可以使用last -f /va…...

2022最新版-李宏毅机器学习深度学习课程-P26RNN-2

一、RNN网络结构 与时间有关的反向传播&#xff08;每次不同&#xff09; 损失函数 实验其实不容易跑&#xff0c;因为他的损失函数曲线幅度很大 画出来差不多是这个样子。突然一下升高是因为从右到左碰到陡峭的地方梯度一下变大了&#xff0c;所以弹回去了。 原作者在训练时…...

docker 配置mongoDB

## 拉取镜像 docker pull mongo## 设置默认账号密码 test:test 默认数据 test docker run -d --name mongo-container -e MONGO_INITDB_ROOT_USERNAMEtest -e MONGO_INITDB_ROOT_PASSWORDtest -e MONGO_INITDB_DATABASEtest -p 27017:27017 mongo...

基于PHP的宠物爱好者交流平台管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...

盘点数据采集中14种常见的反爬策略

引言 随着互联网的飞速发展, 爬虫技术不断演进, 为数据获取和信息处理提供了强大支持。然而, 滥用爬虫和恶意爬取数据的行为日益增多, 引发了反爬虫技术的兴起。在这场看似永无止境的 技术较量 中, 爬虫与反爬虫技术相互博弈、角力。本文将简单过下目前已知的几种反爬策略, 旨…...

直播预告:防御升级-SMC2精准对抗账号劫持和漏洞威胁

当邮箱账号出现疑似被盗风险和遭受外部攻击时&#xff0c;企业管理员需要尽快发现或排除潜在威胁&#xff0c;并采取处置措施&#xff0c;阻止威胁扩大。 那么面对账号失陷风险&#xff0c;企业管理员如何做到账号异常行为的精准检测和即时处置&#xff1f;当账号遭受外部攻击时…...

班主任好物 班级查询系统来啦

哈喽各位&#xff0c;作为一名教育博主&#xff0c;今天我要给大家分享一个班主任的好物——班级查询系统&#xff01;这个系统可真是太方便了呢&#xff0c;那么&#xff0c;这个神秘的班级查询系统到底是什么呢&#xff1f;别急&#xff0c;听我慢慢道来。 班级查询系统&…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...