第7.1章:StarRocks性能调优——查询分析

news2025/1/16 3:59:47

目录

一、查看查询计划

1.1 概述

1.2 查询计划树

1.3 查看查询计划的命令

1.3 查看查询计划

二、查看查询Profile 

2.1 启用 Query Profile

2.2 获取 Query Profile

2.3 Query Profile结构与详细指标 

2.3.1 Query Profile的结构

2.3.2 Query Profile的合并策略

2.3.3 Query Profile的详细指标 

三、Query Hint

3.1 概述

3.2 系统变量 Hint

3.3 Join Hint

    为了优化StarRocks集群性能,需要定期对慢查询进行分析优化,避免慢查询影响整个集群的服务能力。query plan查询计划是FE通过解析sql生成的执行计划,而profile是BE执行查询后的结果,包含了每一步的耗时和数据处理量等数据。

一、查看查询计划

1.1 概述

   在StarRocks中,一条sql语句的生命周期可以分为(简化版)为查询解析(query parsing)查询计划(query plan)、执行(query execution)三个阶段。一般而言,查询解析不会成为查询性能的瓶颈,因为分析型需求的qps(“每秒查询率”或“每秒请求数”)不高。所以决定查询性能的关键就在于查询规划(query plan)和查询执行(query execution)。两者关系是:query plan负责组织算子(scan/join/aggregation)之间的关系,query execution负责执行具体算子。

1.2 查询计划树

    查询规划器用来决定数据库如何具体执行一个 SQL 的,比如用户指定了一个 Join 算子,则查询规划器需要决定具体的 Join 算法,比如是使用 Shuffle 还是 Broadcast;Join顺序是否需要调整以避免笛卡尔积;以及确定最终的在哪些节点执行等等。

  Doris的查询规划器是先将一个 SQL语句转换成一个单机执行计划树,SQL --> PlanNodeTree

    之后,查询规划器会根据具体的算子执行方式、数据的具体分布,将单机查询计划转换为分布式查询计划,即PlanNodeTree --->PlanFragmentTree,分布式查询计划是由多个Plan Fragment 组成的,例如:Plan Fragment 0,Plan Fragment 1,Plan Fragment 2deng 。每个 Fragment 负责查询计划的一部分,各个Fragment之间会通过DataStreamSink和ExchangeNode 算子进行数据的传输。

   

   如上图,我们将单机计划分成了两个 Fragment:F1 和 F2。两个 Fragment 之间通过一个 ExchangeNode 节点传输数据。而一个Fragment 会进一步的划分为多个Instance。Instance 是最终具体的执行实例。划分成多个 Instance 有助于充分利用机器资源,提升一个 Fragment 的执行并发度

1.3 查看查询计划的命令

   query plan可以分为逻辑执行计划(logical query plan)和物理执行计划(physical query plan),本文说的query plan默认指代的都是逻辑执行计划。 通过explain  sql_statement 命令查看query plan。

   ps: Doris中的命令更丰富:查询分析 - Apache Doris

1.3 查看查询计划

    来自StarRocks官网案例:分析查询 | StarRocks

     查询计划涉及的概念: 

 以下面这个query plan查询计划为例,进行分析:

mysql> EXPLAIN select count(*)
from store_sales, 
    household_demographics, 
    time_dim, 
    store
where ss_sold_time_sk = time_dim.t_time_sk
    and ss_hdemo_sk = household_demographics.hd_demo_sk
    and ss_store_sk = s_store_sk
    and time_dim.t_hour = 8
    and time_dim.t_minute >= 30
    and household_demographics.hd_dep_count = 5
    and store.s_store_name = 'ese'
order by count(*) limit 100;

+------------------------------------------------------------------------------+
| Explain String                                                               |
+------------------------------------------------------------------------------+
| PLAN FRAGMENT 0                                                              |
|  OUTPUT EXPRS:<slot 11>                                                      |
|   PARTITION: UNPARTITIONED                                                   |
|   RESULT SINK                                                                |
|   12:MERGING-EXCHANGE                                                        |
|      limit: 100                                                              |
|      tuple ids: 5                                                            |
|                                                                              |
| PLAN FRAGMENT 1                                                              |
|  OUTPUT EXPRS:                                                               |
|   PARTITION: RANDOM                                                          |
|   STREAM DATA SINK                                                           |
|     EXCHANGE ID: 12                                                          |
|     UNPARTITIONED                                                            |
|                                                                              |
|   8:TOP-N                                                                    |
|   |  order by: <slot 11> ASC                                                 |
|   |  offset: 0                                                               |
|   |  limit: 100                                                              |
|   |  tuple ids: 5                                                            |
|   |                                                                          |
|   7:AGGREGATE (update finalize)                                              |
|   |  output: count(*)                                                        |
|   |  group by:                                                               |
|   |  tuple ids: 4                                                            |
|   |                                                                          |
|   6:HASH JOIN                                                                |
|   |  join op: INNER JOIN (BROADCAST)                                         |
|   |  hash predicates:                                                        |
|   |  colocate: false, reason: left hash join node can not do colocate        |
|   |  equal join conjunct: `ss_store_sk` = `s_store_sk`                       |
|   |  tuple ids: 0 2 1 3                                                      |
|   |                                                                          |
|   |----11:EXCHANGE                                                           |
|   |       tuple ids: 3                                                       |
|   |                                                                          |
|   4:HASH JOIN                                                                |
|   |  join op: INNER JOIN (BROADCAST)                                         |
|   |  hash predicates:                                                        |
|   |  colocate: false, reason: left hash join node can not do colocate        |
|   |  equal join conjunct: `ss_hdemo_sk`=`household_demographics`.`hd_demo_sk`|
|   |  tuple ids: 0 2 1                                                        |
|   |                                                                          |
|   |----10:EXCHANGE                                                           |
|   |       tuple ids: 1                                                       |
|   |                                                                          |
|   2:HASH JOIN                                                                |
|   |  join op: INNER JOIN (BROADCAST)                                         |
|   |  hash predicates:                                                        |
|   |  colocate: false, reason: table not in same group                        |
|   |  equal join conjunct: `ss_sold_time_sk` = `time_dim`.`t_time_sk`         |
|   |  tuple ids: 0 2                                                          |
|   |                                                                          |
|   |----9:EXCHANGE                                                            |
|   |       tuple ids: 2                                                       |
|   |                                                                          |
|   0:OlapScanNode                                                             |
|      TABLE: store_sales                                                      |
|      PREAGGREGATION: OFF. Reason: `ss_sold_time_sk` is value column          |
|      partitions=1/1                                                          |
|      rollup: store_sales                                                     |
|      tabletRatio=0/0                                                         |
|      tabletList=                                                             |
|      cardinality=-1                                                          |
|      avgRowSize=0.0                                                          |
|      numNodes=0                                                              |
|      tuple ids: 0                                                            |
|                                                                              |
| PLAN FRAGMENT 2                                                              |
|  OUTPUT EXPRS:                                                               |
|   PARTITION: RANDOM                                                          |
|                                                                              |
|   STREAM DATA SINK                                                           |
|     EXCHANGE ID: 11                                                          |
|     UNPARTITIONED                                                            |
|                                                                              |
|   5:OlapScanNode                                                             |
|      TABLE: store                                                            |
|      PREAGGREGATION: OFF. Reason: null                                       |
|      PREDICATES: `store`.`s_store_name` = 'ese'                              |
|      partitions=1/1                                                          |
|      rollup: store                                                           |
|      tabletRatio=0/0                                                         |
|      tabletList=                                                             |
|      cardinality=-1                                                          |
|      avgRowSize=0.0                                                          |
|      numNodes=0                                                              |
|      tuple ids: 3                                                            |
|                                                                              |
| PLAN FRAGMENT 3                                                              |
|  OUTPUT EXPRS:                                                               |
|   PARTITION: RANDOM                                                          |
|   STREAM DATA SINK                                                           |
|     EXCHANGE ID: 10                                                          |
|     UNPARTITIONED                                                            |
|                                                                              |
|   3:OlapScanNode                                                             |
|      TABLE: household_demographics                                           |
|      PREAGGREGATION: OFF. Reason: null                                       |
|      PREDICATES: `household_demographics`.`hd_dep_count` = 5                 |
|      partitions=1/1                                                          |
|      rollup: household_demographics                                          |
|      tabletRatio=0/0                                                         |
|      tabletList=                                                             |
|      cardinality=-1                                                          |
|      avgRowSize=0.0                                                          |
|      numNodes=0                                                              |
|      tuple ids: 1                                                            |
|                                                                              |
| PLAN FRAGMENT 4                                                              |
|  OUTPUT EXPRS:                                                               |
|   PARTITION: RANDOM                                                          |
|   STREAM DATA SINK                                                           |
|     EXCHANGE ID: 09                                                          |
|     UNPARTITIONED                                                            |
|                                                                              |
|   1:OlapScanNode                                                             |
|      TABLE: time_dim                                                         |
|      PREAGGREGATION: OFF. Reason: null                                       |
|      PREDICATES: `time_dim`.`t_hour` = 8, `time_dim`.`t_minute` >= 30        |
|      partitions=1/1                                                          |
|      rollup: time_dim                                                        |
|      tabletRatio=0/0                                                         |
|      tabletList=                                                             |
|      cardinality=-1                                                          |
|      avgRowSize=0.0                                                          |
|      numNodes=0                                                              |
|      tuple ids: 2                                                            |
+------------------------------------------------------------------------------+
128 rows in set (0.02 sec)

  解析过程:query plan分为 5 个pan fragment,编号从 0 至4,通过从下至上的方式查看query plan。

    step1:最底部的 Plan Fragment 为 Fragment 4,它负责扫描time_dim表,并提前执行相关查询条件 time_dim.t_hour = 8 and time_dim.t_minute >= 30,即谓词下推。这里的time_dim表采用的是聚合表,对于聚合表(Aggregate Key),StarRocks 会根据不同查询选择是否开启预聚合 PREAGGREGATION。以上示例中 time_dim 表的预聚合为关闭状态,此状态之下 StarRocks 会读取 time_dim 的全部维度列,如果当前表包含大量维度列,这可能会成为影响性能的一个关键因素。如果 time_dim 表被设置为根据 Range Partition 进行数据划分(数据分区),Query Plan 中的 partitions 会表征查询命中的分区,无关分区被自动过滤,从而有效减少扫描数据量。如果当前表有物化视图,StarRocks 会根据查询去自动选择物化视图,如果没有物化视图,那么查询自动命中 base table(基表),也就是以上示例中展示的 rollup: time_dim

  step2:当 time_dim 表数据扫描完成之后,Fragment 4 的执行过程也就随之结束,此时它将扫描得到的数据传递给其他 Fragment(各个Fragment之间,通过DataStreamSink和ExchangeNode 算子进行数据的传输。以上示例 EXCHANGE ID : 09 表征了数据传递给了标号为 9 的接收节点。

   Fragment 2,3,4功能类似,只是负责扫描的表不同。而查询中的 Order/Aggregation/Join 算子,都在 Fragment 1 中进行。

  step3:Fragment 1 集成了三个 Join 算子的执行,采用默认的 BROADCAST 方式进行执行,也就是小表向大表广播的方式进行。如果两个 Join 的表都是大表,建议采用 SHUFFLE 的方式进行。目前 StarRocks 只支持 HASH JOIN,也就是采用哈希算法进行 Join。以上示例中的 colocate 字段用来表述两张 Join 表采用同样的分区/分桶方式。如果分区/分桶方式相同,Colocate Join 的过程可以直接在本地执行,不用进行数据的移动。Join 执行完成之后,Fragment 1 就会执行上层的 Aggregation、Order by 和 TOP-N 算子。

二、查看查询Profile 

2.1 启用 Query Profile

   官网文章地址:Query Profile 概述 | StarRocks

    Profile 包含了一个sql查询涉及的所有工作节点的执行信息,有助于我们分析查询性能的瓶颈。将变量 enable_profile 设置为 true 以启用 Query Profile:SET enable_profile = true;

2.2 获取 Query Profile

以下步骤获取 Query Profile:

  1. 在浏览器中访问 http://<fe_ip>:<fe_http_port>
  2. 在显示的页面上,单击顶部导航中的 queries
  3. 在 Finished Queries 列表中,选择您要分析的查询并单击 Profile 列中的链接。

   页面将跳转至相应 Query Profile

2.3 Query Profile结构与详细指标 

2.3.1 Query Profile的结构

   Query Profile 的结构与执行引擎的设计密切相关,由以下五部分组成:

  • Fragment:执行树。一个查询由一个或多个Fragment组成
  • FragmentInstance:每个Fragment可以有多个实例,每个实例称作FragmentInstance,分别由不同的计算节点来执行
  • Pipeline:一个FragmentInstance会被拆分成多个Pipeline,每个Pipeline是一个执行链,由一组首尾相接的 Operator 构成。
  • PipelineDriver:一个 Pipeline 可以有多个实例,每个实例称为 PipelineDriver,以充分利用多个计算核心。
  • Operator:算子,一个 PipelineDriver 由多个 Operator 组成。

2.3.2 Query Profile的合并策略

    同一个Fragment 关联的多个 FragmentInstance 在结构上具有高度相似性。为了减少 Query Profile 的体积,可以将 FragmentInstance 层进行合并,原本的五层结构便简化为三层:

  • Fragment:执行树
  • Pipeline:执行链
  • Operator:算子

 通过一个 Session变量 pipeline_profile_level 来控制这个合并行为,其可选值有2个:

  • 1:合并,即三层结构。默认值。
  • 2:不合并,即保留原始的五层结构。
  • 其他任何数值都会被当成默认值 1

 通常没有必要调整这个参数,就采取默认值1

2.3.3 Query Profile的详细指标 

 太多了,看官网:Query Profile 结构与详细指标 | StarRocks

三、Query Hint

3.1 概述

   Hint是一种指令或注释,显式地向查询优化器建议如何执行查询,Hint 仅在单个查询范围内生效。 StarRocks 目前支持两种 Hint:系统变量 Hint 和 Join Hint

3.2 系统变量 Hint

    在 selec等语句中通过 /*+ ... */ 注释的形式设置一个或多个系统变量 hint。其他语句中如果包含 select 子句(如创建物化视图create materialized view as select,创建视图create view as select),则也可以在该 select 子句中使用系统变量 hint。

 select [/*+ set_var(key=value [, key = value]*) */] ...
#创建物化视图时在 SELECT 子句中通过系统变量 query_timeout 来设置查询执行超时时间。
create materialized view mv 
partition by dt 
distributed by hash(`key`) 
buckets 10 
refresh async 
as select /*+ set_var(query_timeout=500) */ * from dual;

3.3 Join Hint

    针对多表关联查询,优化器一般会主动选择最优的 Join 执行方式(Join Reorder)。在特殊情况下,用户使用 Join Hint显式地指定Join 执行方式。目前 Join Hint 支持的Join执行方式有Broadcast Join、Shuffle Join、Bucket Shuffle Join 和 Colocate Join。

  当Join Hint指定Colocate Join或 Bucket Shuffle Join 时,需要确保表的数据分布情况满足这两种 Join 执行方式的要求,否则用户指定的Join执行方式不生效。

#语法
... join { [broadcast] | [shuffle] | [bucket] | [colocate] | [unreorder]} ...

#说明:使用 Join Hint 时大小写不敏感。

举例:

  • Shuffle Join

     如果需要将表 A、B 中分桶键取值相同的数据行 Shuffle 到相同机器上,再进行 Join 操作,您可以设置 Join Hint 为 Shuffle Join。

select k1 from t1 join [SHUFFLE] t2 on t1.k1 = t2.k2 group by t2.k2;
  • Broadcast Join

   如果表 A 是个大表,表 B 是个小表,则可以设置 Join Hint 为 Broadcast Join。表 B 的数据全量广播到表 A 数据所在的机器上,再进行 Join 操作。Broadcast Join 相比较于 Shuffle Join,节省了 Shuffle 表 A 数据的开销。

select k1 from t1 join [broadcast] t2 on t1.k1 = t2.k2 group by t2.k2;
  • Bucket Shuffle Join

    如果关联查询中 Join 命中表 A 的分桶键 ,且表 A 和表 B 均是大表的情况下,可以设置 Join Hint 为 Bucket Shuffle Join。表 B 数据会按照表 A 数据的分布方式,Shuffle 到表 A 数据所在机器上,再进行 Join 操作。Bucket Shuffle Join 是在 Broadcast Join 的基础上进一步优化,Shuffle B 表的数据量全局只有一份,比 Broadcast Join 少传输了很多倍数据量。

select k1 from t1 join [bucket] t2 on t1.k1 = t2.k2 group by t2.k2;
  • Colocate Join

    如果建表时指定表A 和 B属于同一个 Colocation Group,则表 A 和表 B 分桶键取值相同的数据行一定分布在相同 BE 节点上。当关联查询中 Join命中表 A 和 B 的分桶键,可以设置 Join Hint 为 Colocate Join。 具有相同键值的数据直接在本地 Join,减少数据在节点间的传输耗时,从而提高查询性能。

select k1 from t1 join [colocate] t2 on t1.k1 = t2.k2 group by t2.k2;

  通过explain命令来查看 Join Hint 是否生效。如果返回结果所显示的 Join 执行方式符合 Join Hint,则表示 Join Hint 生效。

explain select k1 from t1 join [colocate] t2 on t1.k1 = t2.k2 group by t2.k2;

参考文章:

StarRocks技术内幕:查询原理浅析

【源码解析系列】 Apache Doris 查询源码解析

Doris的查询计划-腾讯云开发者社区-腾讯云

分析查询 | StarRocks

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1470666.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉基础知识(十五)--卷积神经网络

卷积神经网络简介 CNN--卷积神经网络&#xff0c;是一种前馈神经网络&#xff1b;不同于传统的只有线性连接的神经网络&#xff1b;CNN具有卷积&#xff08;convolution&#xff09;操作、池化&#xff08;pooling&#xff09;和非线性激活函数映射等&#xff1b;经典CNN网络有…

【Linux】--- 详解Linux软件包管理器yum和编辑器vim

目录 一、Linux软件包管理器 - yum1.1 yum和软件包是什么1.2 Linux系统(Centos)的生态1.3 yum相关操作1.4 yum本地配置 二、Linux编辑器 - vim使用2.1 vim的基本概念2.2 vim命令模式命令集2.3 vim末行模式命令集2.4 关于vim的几个相关问题 一、Linux软件包管理器 - yum 1.1 yu…

Codeforce Monsters Attack!(B题 前缀和)

题目描述&#xff1a; 思路&#xff1a; 本人第一次的想法是先杀血量低的第二次想法是先搞坐标近的第三次想法看到数据量这么大&#xff0c; 我先加个和看看貌似我先打谁都行&#xff0c;由此综合一下&#xff0c; 我们可以把每一个不同的坐标当作一轮从最小的坐标开始&#x…

Vue+SpringBoot打造在线课程教学系统

目录 一、摘要1.1 系统介绍1.2 项目录屏 二、研究内容2.1 课程类型管理模块2.2 课程管理模块2.3 课时管理模块2.4 课程交互模块2.5 系统基础模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示4.1 管理后台4.2 用户网页 五、样例代码5.1 新增课程类型5.2 网站登录5.3 课…

机器学习打分函数在分子对接中的应用系列-GB_Score

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、GB-Score是什么&#xff1f;二、文献复现 -训练和验证环境1. GB score验证虚拟环境的配置2. Usage1- Preparing ligand and protein file2- Generating features3 - Repeat and extend current…

打印水仙花数---c语言刷题

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 题述 求出0&#xff5e;100000之间的所有“水仙花数”并输出。 “水仙花数”是指一个n位数&#xff0c;其各位数字的n次方之和确好等于该数本身&#xff0c;如:153&#…

openssl3.2 - crypto-mdebug被弃用后, 内存泄漏检查的替代方法

文章目录 openssl3.2 - crypto-mdebug被弃用后, 内存泄漏检查的替代方法概述笔记查看特性列表openssl3.2编译脚本 - 加入enable-crypto-mdebug看看有没有替代内存诊断的方法?main.cppmy_openSSL_lib.hmy_openSSL_lib.c备注备注END openssl3.2 - crypto-mdebug被弃用后, 内存泄…

sonar-java 手写一个规则-单元测试分析

前言 最近做项目&#xff0c;定制sonar规则&#xff0c;提高Java代码质量&#xff0c;在编写的sonar规则&#xff0c;做验证时&#xff0c;使用单元测试有一些简单的心得感悟&#xff0c;分享出来。 自定义规则模式 sonar的自定义规则很简单&#xff0c;一般而言有2种模式可…

解决vulhub漏洞环境下载慢卡死问题即解决docker-valhub漏洞环境下载慢的问题

解决vulhub环境下载慢/卡 当前环境为&#xff1a;ubuntu20 1.在 cd /etc/docker/目录下创建或修改daemon.json文件 sudo touch daemon.json编辑daemon.json文件 sudo vim daemon.json2.填写阿里云镜像地址&#xff1a; { "registry-mirrors":["https://6kx…

UE5 C++ Gas开发 学习记录(三)

添加AuraPlayerState,AuraAbilitySystemComponentBase和AuraAttributeSet 在Build.cs里添加 // Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; public class MyGas : ModuleRules { public MyGas(ReadOnlyTargetRules Target) : base(Target) { P…

Android pixel6网页线刷官方镜像

背景 p6-7系pixel更新Android 13,首次引入了防回滚机制,Android13系统检测到属于Android12版本的旧bootloader就会直接红字警告拒绝引导,多次引导就会成为收藏品!(除非充钱) 今天收到了新的pixel6,想着以后刷机刷内核肯定频繁,就先打个预防针。 网页线刷官方镜像 查…

RabbitMQ-消息队列:优先级队列、惰性队列

20、优先级队列 在我们系统中有一个订单催付的场景&#xff0c;我们的客户在天猫下的订单&#xff0c;淘宝会及时将订单推送给我们&#xff0c;如果在用户设定的时间内未付款那么就会给用户推送一条短信提醒&#xff0c;很简单的一个功能对吧。 但是&#xff0c;天猫商家对我…

如何增加层次厚度?

Q 老师&#xff0c;我在做一个斧头武器&#xff0c;如何在平面上增加厚度和层次呢&#xff1f; A 选中这几个线&#xff0c;点连接就会出现中线&#xff0c;把中线稍作调整即可~

[嵌入式系统-35]:RT-Thread -20- 新手指南:在Keil MDK-ARM 模拟器上运行RT-Thread

目录 前言&#xff1a; 一、Keil MDK-ARM 模拟器概述 1.1 Keil概述 1.2 Keil MDK-ARM 1.3 Keil MDK-ARM软件仿真模拟器 1.4 Keil模拟器支持的CPU类型 二、Keil MDK ARM安装 前言&#xff1a; 一般嵌入式操作系统因为它的特殊性&#xff0c;往往和硬件平台密切相关连&am…

【C++精简版回顾】12.友元函数

1.友元函数 1.class class MM { public:MM(int age,string name):age(age),name(name){}friend void print(MM mm); private:int age;string name;void print() {cout << age << "岁的" << name << "喜欢你" << endl;} }; f…

DAY31--learning English

一、积累 1.stiff 2.curve 3.pungent 4.mellow 5.marinate 6.drain 7.corrupt 8.magnet 9.liver 10.stew 11.maid 12.sonogram 13.folk 14.anecdote 15.altar 16.spaghetti 17.ammunition 18.shield 19.beacon 20.hanger 二、练习 1.牛津原译 stiff /stɪf/ ( stiffer stiff…

编程的基础:理解时间和空间复杂度

编程的基础&#xff1a;理解时间和空间复杂度 时间复杂度空间复杂度示例常数时间复杂度 O(1)线性时间复杂度 O(n)线性对数时间复杂度 O(n log n)二次时间复杂度 O(n^2)指数时间复杂度 O(2^n) 空间复杂度示例常数空间复杂度 O(1)线性空间复杂度 O(n)线性对数空间复杂度 O(log n)…

流浪动物救助平台:Java开发的实践与思考

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

获取tensorflow lite模型指定中间层的输出

以mobilenet v2为例子&#xff0c;我已经训练好了模型&#xff0c;有tflite格式和onnx格式两种模型的权重文件&#xff0c;我想获取tflite模型在推理阶段neck部分的输出。 查看onnx模型得到neck最后一层位置 使用netron查看onnx模型结构 从name中能知道Reshape是neck的最后一…

【蓝桥杯】拓扑排序

一.拓扑排序 1.定义&#xff1a; 设G&#xff08;V&#xff0c;E&#xff09;是一个具有n个顶点的有向图&#xff0c;V中的顶点序列称为一个拓扑序列&#xff0c;当且仅当满足下列条件&#xff1a;若从顶点到有一条路径&#xff0c;则在顶点序列中顶点必在之前。 2.基本思想…