Presto

news2024/11/16 5:25:48

Presto

Presto基本介绍

前言

Presto是一款Facebook开源的MPP架构的OLAP查询引擎,可针对不同数据源执行大容量数据集的一款分布式SQL执行引擎。因为工作中接触到Presto,研究它对理解SQL Parser、常见算子的实现(如SQL中table scan,join,aggregation)、资源管理与调度、查询优化(如向量化执行、动态代码生成)、大数据下各个组件为何适用不同场景等等都有帮助。我希望通过这个系列可以了解一条SQL在大数据场景下该如何高效执行。233酱准备不定时持续更新这个系列,本文主要从Presto的使用举例,Presto的应用场景、Presto的基本概念三个部分来初步介绍Presto。

Presto的使用举例

比如说,你想对存储在不同数据源中的数据,如HDFS、Mysql、HBase等通过一个SQL做查询分析,那么只需要把每一个数据源当成是Presto的Connector,对应实现Presto SPI暴露出的Connector API就可以了。

img

hbase 和 es 的Join查询举例

Presto官方版和Presto社区版已经支持了很多Connector,社区版吕胜一筹。至于两者有何区别,吃瓜群众可以前往文末参考资料。简而言之,都主要由Facebook那帮大佬核心维护。社区版更新更为频繁,但高版本需要JDK11才能支持;官方版JDK8就行,官方版的Star数是社区版的10倍左右,选哪个就一目了然了吧。

Presto的应用场景

Presto是为了处理TB/PB级别的数据查询和分析,它是OLAP(Online Analytical Processing)领域的一个计算引擎。参考资料[1]提到了Presto在Facebook中的使用场景有:

报表和大盘查询

做过报表和大盘的小伙伴应该对这个场景下复杂的SQL有所了解。这个场景下的使用用户是Facebook内部或外部人员,通常要求:高QPS,低时延(<1s)

Adhoc分析

Ad hoc是拉丁文「for this purpose」的意思,Adhoc query的查询特点是海量、实时、灵活。数据量如PB级别以上,时延秒-分钟级别,灵活性举例子如下:

var adhoclQuery = "SELECT * FROM table WHERE id = " + myId;

var sqlQuery = "SELECT * FROM table WHERE id = 1";

adhoclQuery的结果取决于参数“myId”的值,它的结果不能被预计算。sqlQuery的结果每次执行可认为都一样,它的结果可以被预计算。

典型应用场景如:用户趋势分析,产品市场洞察等。主要用户是内部数据分析人员。

批处理

批处理通常是指更大数据量的一个分析,可容忍高时延(小时-天级别)。Presto是为了低时延而设计的,它属于内存型的MPP架构。并不适合类似Spark那样的长时间离线跑批。参考资料[1]的视频中分析了两者架构的区别,Presto跑批的限制。这里我截几张PPT帮助大家理解:
两者的架构区别:

img

Presto跑批的限制原因:

img

Presto跑批的条件:

img

所以他们提供了Presto on Spark方案,这样做的好处是可以统一用户使用的SQL方言差异,UDF差异。

img

当然,业界除了Facebook还有公司把Presto跑在Spark上来跑批吗?我没有搜到相关信息。

Presto的基本概念

前面主要谈了Presto的使用场景,下面简要从 Presto的架构和基本术语上介绍Presto。

Presto架构

Presto的架构图如下:

img

Presto集群包含1个Coordinator节点和1-多个Worker节点。

Coordinator节点 负责接受客户端请求、解析SQL语句、生成并优化分布式逻辑执行计划、将计划中的任务调度到Worker节点上,并跟踪Worker节点和任务的执行状态。

Worker节点 负责任务的执行,接受Coordinator节点的调度。

从中我们可以粗略看出一条SQL在Presto中的执行过程为:

1).Client发送一个SQL语句到Coordinator节点
2).Coordinator节点把请求放到队列中,解析和分析其中的SQL语句;生成并且优化分布式逻辑执行计划。
3).Coordinator节点会把这个Plan分解为任务,由多个Worker分布式执行。

要想了解具体的SQL执行过程,我们得先介绍下Presto的基本概念,也为下篇介绍「Presto为什么是OLAP领域的实时计算引擎」的文章作准备>_<

基本术语

我们很容易知道 *statements*queries* 的意思。作为一个使用者我们也应该熟悉 stages、 splits* 这些概念使Presto尽可能高效执行queries;作为一个Presto管理员,应该理解 stages* 是如何映射为tasks***的,包含 *drivers* 集合 的 *task* 是如何处理数据的。以下将从一般到具体介绍Presto的基本术语。

Server Types

Presto包含两种类型的服务端节点:coordinators 和 workers。

Coordinator

Presto中的Coordinator节点负责解析SQL语句,生成并优化物理执行计划,管理Presto worker节点。它是Presto运行的“大脑”。它也是客户端提交SQL语句的节点。每个运行的Presto集群包含1个Coordinator节点和1-多个Worker节点。一个服务示例可同时担任这两种节点角色。

Coordinator节点一直跟踪每个Worker节点的状态和协调查询计划的执行。Coordinator生成一个物理执行计划模型,它包含一系列的stages,而stages会转化为一系列的任务跑在workers节点上。

Coordinator通过REST API和workers 、 clients通信。

Worker

Worker节点负责执行tasks,处理数据。它从connectors中捞取数据,并且Worker节点之间可交换中间数据。coordinator节点负责合并workers的结果,并且返回结果给Client。

当一个Worker节点开始工作后,它会把自己注册到coordinator的注册服务上,从而使Coordinator节点可将task调度到自己执行。

Workers和其他Workers、coordinators之间都是通过REST API通信。

Data Sources

诸如connector, catalog, schema, and table这些术语,都是和Presto的模型中:一种特定的数据源有关。

Connector

connector是Presto中的一个数据源,可以是Hive、Mysql、Elasticsearch、HBase等。你可以把connector认为是一种数据库驱动,只要实现Presto SPI 中暴露的相关接口,就可以接入一种Connector。

Presto自带一些connectors:如JMX,System connector用来获取system tables的,Hive connector,TPCH connector 用来性能测试用的,等等。

每一个catalog和一个特定的connector关联。每一个catalog配置文件中有一个connector.name属性,它是被catalog manager用来为一个给定的catalog创建一个connector。一个catalog可以使用相同的connector获取类似数据库的两个实例。

Catalog

Presto catalog包含schemas和通过Connector持有的数据源引用。比如:你可以配置一个ES catalog,就可以通过ES Connector提供从ES中获取数据。

#elasticsearch.properties

connector.name=elasticsearch
elasticsearch.host=es host
elasticsearch.port=9200
elasticsearch.default-schema-name=es

当你在Presto上执行SQL时,你就在运行1-多个catalogs.在Presto上定位一张表,是通过一个catalog的全限定名确定的,如hive.test_data.test代表在hive catalog,test_data schema 下的一张test table.

Catalogs属性文件是存储在Presto配置目录的,默认是Presto主安装文件下的etc目录下。

Schema

Schemas是一种组织tables的方式。一个catalog和一个catalog定义了一个可被查询的table集合。对于MySQL这种关系型数据库,Presto的schema是和MySQL中的schema相同的概念。对于其他类型的connector,如ES, Presto的schema是用来组织一些表到特定的schema中,从而使底层的数据源能够在Presto层面说得通。

Table

table是一组无序的Row集合,Row是一组有类型的column集合。和关系型数据库中的概念一样,table的映射是由connector中定义的。

Query Execution Model

Presto执行SQL语句,并且转化为执行计划,在由coordinator 和 workers组成的分布式集群上运行。

Statement

Presto执行兼容ANSI标准的SQL。这些SQL statements包含子句,表达式,条件。
Presto把Statement 和 Query区分开是因为:在Presto中,statements是指Client提交上来的SQL语句,如:

SELECT * FROM table WHERE id = 1

query是指Presto执行statement时,生成的一个物理执行计划,并且之后分布式的在一系列workers上执行它。

Query

当Presto解析一个statement时,它会把statement转化为一个query,并且创建一个分布式的执行计划,然后转化为一系列的有关联性的stages运行在Presto workers上。当你在Presto获取一个query的信息时,得到的是每个参与执行的组件的一个当前结果快照。

statement可认为是Client提交上来的SQL语句,query指的是执行一个statement有关的配置和组件实例信息。query围绕者stages, tasks, splits, connectors,其他组件和数据源一起工作,以产生最终结果。

Stage

当Presto执行一个query时,它会把执行分为一个有层次结构关系的stages.比如SQL语句:

img

会先转化为逻辑执行计划:

img

然后会转化为实现这个分布式逻辑执行计划的一个层次结构的stage:

img

这个层次结构的stages可以理解为一个一个树。每个query都有一个root stage负责其他stages的输出结果聚合。stages是coordinator节点用来生成一个分布式查询计划的模型,但是stages它们自己并不跑在Presto workers节点上。

Task

一个stage是由一系列的tasks分布式运行在Presto workers上。

在Presto架构中,task是“work horse”。因为分布式查询计划被分解为一系列stage,然后被转换为task,这些task随后执行或被进一步split。一个task有输入和输出,就像一个stage可以有一系列的tasks并行执行一样,一个task可以由一系列的drivers并行执行。

Split

Split是较大数据集的一个分片。分布式查询计划的最低级别的stage(如上图中的Stage3/Stage4)通过来自connectors得到的splits集合获取输入数据,更高级别的中间Stage(如上图中的Stage2/Stage1)从下一层stage中获取输入数据。

当Presto调度一个query时,coordinator节点会查询连接器的SPI接口获得一个表可用的所有split集合。coordinator跟踪哪些机器正在运行哪些task,以及哪些任务正在处理哪些split。

Driver

Task包含一个或多个并行的driver。driver对数据进行操作,并结合operators产生输出,然后结果由一个task聚合,然后传递到另一个stage的另一个task。driver是一系列operators实例,或者您可以将driver看作内存中的operator的物理集合。它是Presto体系结构中并行的最低级别。一个driver有一个输入和一个输出。

Operator

一个operator消费、转换和生产数据。例如,一个table scan operator从一个connector中获取数据并生产出可由其他operator消费的数据,一个filter operator通过对输入数据应用谓词(过滤条件)并生成一个子集。

Exchange

Exchanges为一个query的不同stage在Presto节点之间传递数据。task使用一个exchange client,生产数据到一个output buffer中,并且消费其他task产生的数据。

Presto安装部署

1.版本选型

hadoop-3.3.5

hive-3.1.3

presto-280

2.Presto 简介

2.1 Presto 优势

多数据源,支持SQL,自定义扩展Connector

混合计算(同一种数据源的不同库 or表;将多个数据源的数据进行合并)

低延迟,高并发,纯内存计算引擎,高性能

2.2 Presto 架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LAT5uzKN-1683615865004)(img/jiagou.png)]

# presto提供插件化的connector来支持外部数据查询,原生支持hive、cassandra、elasticsearch、kafka、kudu、mongodb、mysql、redis等众多外部数据源;
1.coordinator(master):负责meta管理,worker管理;接收查询请求,解析SQL生成执行计划
2.worker:执行任务的节点,负责计算和读写
3.connector:连接器(Hadoop相关组件的连接器,RDBMS连接器)
4.discovery service:内嵌在coordinator节点中,也可以单独部署,用于节点心跳;worker节点启动后向discovery service服务注册,coordinator通过discovery service获取注册的worker节点

2.3 Presto数据模型

presto采取三层表结构:
catalog 对应某一类数据源,例如hive的数据,或mysql的数据
schema 对应mysql中的数据库
table 对应mysql中的表

2.4 Presto 执行过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yx8vcBm8-1683615865005)(img/zhixingguocheng.png)]

1、coordinator接到SQL后,通过SQL语法解析器把SQL语法解析变成一个抽象的语法树AST(描述最原始的用户需求),只是进行语法解析如果有错误此环节暴露
2、语法符合SQL语法,会经过一个逻辑查询计划器组件,通过connector 查询metadata中schema 列名 列类型等,将之与抽象语法数对应起来,生成一个物理的语法树节点 如果有类型错误会在此步报错
3、如果通过,会得到一个逻辑的查询计划,将其分发到分布式的逻辑计划器里,进行分布式解析,最后转化为一个个task
4、在每个task里面,会将位置信息解析出来,交给执行的plan,由plan将task分给worker执行

3.Presto 安装

3.1 安装

#server
tar -zxvf /opt/soft/presto-server-0.280.tar.gz
mv /opt/soft/presto-server-0.280/ /opt/soft/presto-server

#1.把 presto-cli-0.280.jar 复制到 /opt/soft/presto-server/bin 目录下
cp /opt/soft/presto-cli-0.280-executable.jar /opt/soft/presto-server/bin

#2.presto-cli-0.280.jar 重命名 presto-cli 
mv /opt/soft/presto-server/bin/presto-cli-0.280.jar /opt/soft/presto-server/bin/presto-cli 

#3.增加 presto 的执行权限
chmod +x /opt/soft/presto-server/bin/presto-cli

3.2 配置 Presto

1.配置数据目录
#最好安装在 presto server 安装目录外
mkdir /opt/soft/presto-server/data
2.创建配置文件
#1.在 presto server 安装目录 /opt/soft/presto 创建 etc 文件夹
mkdir /opt/soft/presto-server/etc

#2.在 /opt/soft/presto/etc 下创建 config.properties,jvm.properties,node.properties,log.properties 文件
vim config.properties
coordinator=true   #work节点需要填写false
node-scheduler.include-coordinator=true  #是否允许在coordinator上调度节点只负责调度时node-scheduler.include-coordinator设置为false,调度节点也作为worker时node-scheduler.include-coordinator设置为true
http-server.http.port=8085
query.max-memory=1GB
query.max-memory-per-node=512MB
query.max-total-memory-per-node=512MB
discovery-server.enabled=true    #Presto 通过Discovery 服务来找到集群中所有的节点,每一个Presto实例都会在启动的时候将自己注册到discovery服务;  注意:worker 节点不需要配 discovery-server.enabled
discovery.uri=http://spark03:8085  #Discovery server的URI。由于启用了Presto coordinator内嵌的Discovery 服务,因此这个uri就是Presto coordinator的uri
# (Presto集群coordinator和worker的JVM配置是一致的)
vim jvm.config  
-server
-Xmx2G
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError
vim node.properties
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-ffffffffffff01  #每个节点需要不同
node.data-dir=/opt/soft/presto-server/data
vim log.properties
com.facebook.presto=DEBUG

3.3 配置 connector

#1.在 /opt/soft/presto-server/etc 创建 catalog 目录
mkdir /opt/soft/presto-server/etc/catalog

#2.在 catalog 目录下 创建 hive connector
vim hive.properties
connector.name=hive-hadoop2  #注意 connector.name 只能是 hive-hadoop2 
hive.metastore.uri=thrift://spark03:9083
hive.config.resources=/opt/soft/hadoop3/etc/hadoop/core-site.xml,/opt/soft/hadoop3/etc/hadoop/hdfs-site.xml
#3.在 catalog 目录下 创建 mysql connector
vim mysql.properties
connector.name=mysql
connection-url=jdbc:mysql://spark03:3306
connection-user=root
connection-password=Lihaozhe!!@@1122

3.4 配置环境变量

vim /etc/profile
export PRESTO_HOME=/opt/soft/presto-server
export PATH=$PATH:$PRESTO_HOME/bin
source /etc/profile

4.启动 presto

注意:Presto requires Java 8u151+,需要jdk 1.8.151 以上,否则 PrestoServer 进程会自动死亡

#后台启动 (日志在 数据目录 /opt/soft/presto/data/var/log)
/opt/soft/presto-server/bin/launcher start

#调试启动
/opt/soft/presto-server/bin/launcher --verbose run

# 主要在CentOS8操作系统中需要单独安装python3
yum -y install python3
python3 /opt/soft/presto-server/bin/launcher.py start
python3 /opt/soft/presto-server/bin/launcher.py --verbose run

4.1 访问 presto webui http://saprk03:8085

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A1GvuybD-1683615865005)(img/image-20211114173714641.png)]

5.测试

5.1 启动 presto cli

#在 presto server 安装目录下执行
./bin/presto-cli --server spark03:8085
java -jar presto-cli --server spark03:8085
# 查看连接的数据源
show catalogs;

presto-cli --server spark03:8085 --catalog hive --schema lihaozhe;
show tables;
#查看 mysql 中的库
show schemas from mysql;

Presto4Py

# pip3 install pyhive[presto]
from pyhive import presto

if __name__ == 'main':
    cursor = presto.connect(host="saprk03",port="8085",catalog="hive",schema="default").cursor()
    cursor = execute("select * from person limit 10")
    println(cursor.fetchall())
from sqlalchemy import *
from sqlalchemy.engine import create_engine
from sqlalchemy.schema import *

if __name__ == 'main':
    engine = create_engine("presto://spark03:8085/hive/lihaozhe")
    table = Table('person',MetaData(bind=engine),autoload=True)
    num = select([func.count(*)],from_obj=table).calar()
    println("row count = {}".format(num))

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

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

相关文章

MySQL行锁、表锁间隙锁

事务隔离级别的实现原理&#xff1a;锁MVCC 表级锁&行级锁 表级锁&#xff1a;对整张表加锁。开销小&#xff0c;加锁快&#xff0c;不会出现死锁&#xff1b;锁粒度大&#xff0c;发生锁冲突的概率高&#xff0c;并发度低。 行级锁&#xff1a;对某行记录加锁。开销大&a…

论 spring 的三级缓存

论 spring 的三级缓存 预备知识 bean的生命周期 bean 的生命周期 为何会出现循环引用 这个问题只是出现在spring 容器的机制中&#xff0c;其实我们代码中很简单就解决了。 假设A 对象里需要注入一个B属性&#xff0c;B 对象里面需要注入一个A 属性。根据Bean 的生命周期&…

【原创】运维工程师涨薪计划,chatGPT帮你做规划

文章目录 1、运维工程师怎么涨薪呢&#xff1f;a&#xff09;加大深度b&#xff09;加大广度 2、运维工程师何处去呢&#xff1f;3、chatGPT告诉你3年、5年、10年运维和开发的现状&#xff1b;有运维经验的工程师&#xff0c;搞开发好吗薪资会有显著提升吗以数据证明&#xff0…

校园食堂明厨亮灶AI分析系统 yolov5

校园食堂明厨亮灶AI分析系统通过yolov5网络模型技术&#xff0c;校园食堂明厨亮灶监控分析模型算法针对校园餐厅后厨不按要求戴口罩、不穿厨师帽、陌生人员进入后厨、厨师不穿厨师服、上班时间玩手机、老鼠识别等行为自动识别抓拍告警。Yolo算法&#xff0c;其全称是You Only L…

电脑缺少msvcp140.dll怎么办,缺少msvcp140一键修复方法

电脑缺少msvcp140.dll怎么办&#xff1f;这个问题相信不少小伙伴都遇到过&#xff0c;msvcp140.dll文件是很多软件跟游戏运行必须用到的文件&#xff0c;如果丢失或者损坏&#xff0c;很多软件都会无法打开运行。其实知道知道方法&#xff0c;修复起来其实也不会很难&#xff0…

ModelViewSet额外路由参数 与 ADMIN事件触发

ModelViewSet额外路由参数 用了DefaultRouter&#xff0c;那么在URL匹配时带路径参数&#xff0c;只有update、delete、retrieve能带&#xff0c;关键是匹配pk还是写死的&#xff0c;我们需要对任意参数&#xff0c;同时还能修改方法命名。 咋搞&#xff1f;很简单。比如我们…

JS案例:前端Iframe及Worker通信解决思路

目录 前言 Iframe通信 Worker通信 实现思路 实现过程 MessageCenter类 IPC类 Server类 Client类 PeerToPeer 功能演示 基础功能 父子通信 兄弟通信 父子兄弟通信 其他功能 函数调用 索引标识 卸载页面 重置页面 批量执行 批量操作 总结 前言 在前端开发…

虚拟机VMware Tools安装步骤

Vmware tools是虚拟机中一款超级增强工具&#xff0c;可以让我们更加方便使用虚拟机&#xff0c;能实现主机与虚拟机之间的文件共享&#xff0c;这篇文章主要介绍了虚拟机VMware Tools安装步骤,需要的朋友可以参考下 本人安装VMware Tools 的需求是 在Linux虚拟机和我的Windo…

Linux学习记录——이십삼 进程信号(2)

文章目录 1、可重入函数2、volatile关键字3、如何理解编译器的优化4、SIGCHLD信号 1、可重入函数 两个执行流都执行一个函数时&#xff0c;这个函数就被重入了。比如同一个函数insert&#xff0c;在main中执行时&#xff0c;这个进程时间片到了&#xff0c;嵌入了内核&#xf…

博客系统 —— Servlet 实现(前后端分离)(详细+整体代码+效果图)

目录 一、项目效果展示 二、创建 Servlet 项目 三、编写数据库的操作代码 1、创建数据库/表结构&#xff08;数据库设计&#xff09;&#xff08;Model&#xff09; 2、封装数据库操作&#xff08;Model&#xff09; &#xff08;1&#xff09;先创建 DBUtil 封装数据库连…

Etsy总是不出单怎么办?出单后怎么操作?

如果您在Etsy上总是无法出单&#xff0c;可以尝试以下几个步骤&#xff1a; 1、检查您的商品列表是否符合Etsy的要求&#xff0c;包括商品描述、价格、运费等信息是否准确无误。 2、确认您的账户信息是否完整&#xff0c;包括银行账户、信用卡信息等。 3、检查您的店铺设置是否…

socket API的使用+client/server代码演示+封装socket模块

前言&#xff1a;本章旨在讲解常见的socket API及其使用练习&#xff0c;尾部有封装好的&#xff08;socket相关的一些系统函数加上错误处理代码包装成新的函数&#xff09;模块wrap.c 目录 一、socket模型创建流程图 1&#xff09;socket函数 2&#xff09;bind函数 3&am…

Altium软件中相同模块布局布线的方法

文章目录 1、原理图设计1、绘制xxx.SchDoc&#xff0c;并设置port。具体方法&#xff1a;Place→Port。2、新建顶层原理图&#xff1a;可以命名为xxx_TOP3、repeat 原理图&#xff0c;将这里从XXX_SingleDut 改为 Repeat(S,1,12)4、以总线的方式出线&#xff0c;如下&#xff1…

网络安全CVE 漏洞分析及复现

漏洞详情 Shiro 在路径控制的时候&#xff0c;未能对传入的 url 编码进行 decode 解码&#xff0c;导致攻击者可以绕过过滤器&#xff0c;访问被过滤的路径。 漏洞影响版本 Shiro 1.0.0-incubating 对应 Maven Repo 里面也有 【一一帮助安全学习&#xff0c;所有资源获取一一…

NetBackup 10.2 新功能介绍:PostgreSQL 和 MySQL 自动化恢复达成

NetBackup 10.2 新功能介绍&#xff1a;PostgreSQL 和 MySQL 自动化恢复达成 原文来自&#xff1a;VERITAS 中文社区 2023-04-27 在执行恢复任务时&#xff0c;手动提取、更新数据库和实例并将其附加到 PostgreSQL 和 MySQL 是常规操作。而在最新的 NetBackup 10.2 版本中&am…

数据可视化工具 - ECharts以及柱状图的编写

1 快速上手 引入echarts 插件文件到html页面中 <head><meta charset"utf-8"/><title>ECharts</title><!-- step1 引入刚刚下载的 ECharts 文件 --><script src"./echarts.js"></script> </head>准备一个…

apc-service-bus项目Docker镜像发布

apc-service-bus项目Docker镜像发布 1. 提交代码到Gitee代码仓&#xff0c;通过建木将项目打包到服务器 1.1 可直接打开访问建木&#xff0c;无有不熟悉建木发布流程的请咨询其他同事或者自行研究 建木地址&#xff1a;http://10.11.148.21/ 1.2 找到bus的开发环境部署执行…

神经网络全连接层数学推导

全连接层分析 对于神经网络为什么都能产生很好的效果虽然其是一个黑盒&#xff0c;但是我们也可以对其中的一些数学推导有一定的了解。 数学背景 目标函数为 f ∣ ∣ m a x ( X W , 0 ) − Y ∣ ∣ F 2 &#xff0c;求 ∂ f ∂ W , ∂ f ∂ X , ∂ f ∂ Y 目标函数为f ||ma…

SpringBoot项目如何打包成exe应用程序

准备 准备工作&#xff1a; 一个jar包&#xff0c;没有bug能正常启动的jar包 exe4j&#xff0c;一个将jar转换成exe的工具 链接: https://pan.baidu.com/s/1m1qA31Z8MEcWWkp9qe8AiA 提取码: f1wt inno setup&#xff0c;一个将依赖和exe一起打成一个安装程序的工具 链接:…

设计模式——代理模式(静态代理、JDK动态代理、CGLIB动态代理)

是什么&#xff1f; 如果因为某些原因访问对象不适合&#xff0c;或者不能直接引用目标对象&#xff0c;这个时候就需要给该对象提供一个代理以控制对该对象的访问&#xff0c;代理对象作为访问对象和目标对象之间的中介&#xff1b; Java中的代理按照代理类生成时机不同又分…