使用秘籍|如何实现图数据库 NebulaGraph 的高效建模、快速导入、性能优化

news2024/12/30 1:49:31

本文整理自 NebulaGraph PD 方扬在「NebulaGraph x KubeBlocks」meetup 上的演讲,主要包括以下内容:

  • NebulaGraph 3.x 发展历程
  • NebulaGraph 最佳实践
    • 建模篇
    • 导入篇
    • 查询篇

NebulaGraph 3.x 的发展历程

NebulaGraph 自 2019 年 5 月开源发布第一个 alpha 版本以来,陆陆续续发布了 2.0 GA,到现在 v3.6.0,已经是 v3.x 版本中比较后期的版本了。从 3.x 开始,基本上保持了三个月(一个季度)发一个 y 版本的节奏,从 v3.1 到 v3.2,到现在的 v3.6。(演讲时 v3.6 尚未发布,所以没有相关内容展示)

而这几个版本主要是在完备性、性能,稳定性以及易用性上的优化。从 NebulaGraph 作为一款图数据库的产品定位上来说,核心应用场景是 TP 场景,而对 TP 型数据库产品来说,有几个特性是非常重要的:

  • 稳定:数据库作为底层的基础设施,许多业务是基于数据库运行的,是在线的系统,因此稳定性是一个非常重要的特性。在 NebulaGraph v3.4 版本,包括最新版本的 v3.6 版本中,系统的稳定性得到了非常大的提升和改善;
  • 性能:因为 NebulaGraph 定位是一个 TP 的数据库产品,因此性能,包括高吞吐量是至关重要的;
  • 易用:一个好的产品要如何让用户更好地用起来,降低用户的学习成本,也是需要考虑到的;

针对这些特性,我们在 v3.x 这 5 个版本中做了这些尝试:

稳定性

在 v3.x 开始,NebulaGraph 引入 fuzzer,极大提升测试效率。fuzzer 可基于 nGQL(NebulaGraph 的查询语言)的语法进行灵活组合,生成人为不能拟定的查询语句,由此让测试更加完善,从而提高了稳定性。

此外,版本新特性部分还新增 Memory Tracker。图数据库不同于其他数据库,数据一直处于持续地遍历、迭代中,因为即便是数据量不大的情况下,数据的迭代会导致它的结果异常大,这就造成了内存的管理压力。在 v3.4 版本中,NebulaGraph 引入了 Memory Tracker 机制,从论坛的用户反馈上,可以看得出来相关的 OOM 问题大幅度减少了。这里可以阅读下《内存管理实践之 Memory Tracker》;

性能提升

图的经典查询一般包括 K 跳(K-hop)、子图和路径查询。K 跳就是从一个点出发,比如说从我出发,去找寻我好友(一跳)的好友(两跳),这种查询,可能社交或者反欺诈的场景中使用会比较多。此外,就是子图,比如说我现在从一个点出发,找到他的周围的关联的一群人,以及这一群人关联的另外一群人,这时候就可能会用到子图的功能。还有就是路径查询,像是企业和企业之间的关联关系之类的,就比较适合用路径,来找寻二者的关联。在 v3.x 中,这几个图的经典查询性能都有大幅度的提升的,具体大家可以看论坛的性能报告:自测和他测报告合集;

上面提到过内存管理的难点,除了 Memory Tracker 机制之外,属性裁剪能提升内存的利用率,在 NebulaGraph 中如果查询不需要用到某个属性,就会将其裁剪掉,从而提升内存利用率。

易用性

NebulaGraph 在 v2.x 开始支持 openCypher,一开始是比较基础的 openCypher 语法;在 v3.x 开始,NebulaGrpah 做了一个语法完善,像是 OPTIONAL MATCH、多 MATCH 等语法支持,全面覆盖了国际图基准测试之一的 LDBC-SNB 支持的图查询。

此外,在 v3.5 开始支持了 UDF 功能,这个功能是由社区用户 zhaojunnan 提供支持的,它可以用来帮助实现一些内核暂时不支持的功能。这里就不详细展开 UDF 的说明了,具体大家可以看《NebulaGraph UDF 功能的设计与背后的思考》;

最后一点是全文索引优化,这个在后面章节会详细讲述。

NebulaGraph 的最佳实践

在这个部分主要分为:建模、数据导入、查询等三大内容。

数据建模

数据膨胀

这是社区用户在交流群里反馈的一个问题:

  1. 数据导入之后占用硬盘空间极大,60 MB 的文件导入之后,Storage 占用了 3.5 G;
  2. Storage 服务占用内存很高
  3. 并发量大的时候,会出现 ConnectionPool 不够的情况;
  4. 3 跳查询本来就很慢么?我看官方的 Benchmark 数据规模大的时候会慢,但是当前我们数据量也不是很大;

目前的数据情况:点 594,952,边 798,826。同时,边和点均建了 1 个索引:

所以它有什么问题呢?

在图数据库 NebulaGraph 中,有个概念叫做 Space,Space里有一个概念是 VID type,VID 是 NebulaGraph 中非常关键、重要的概念,所有的数据字段都是通过 VID 来进行唯一索引,类似主键的概念。比如上图的中间部分:点结构和边结构,可以看到结构中都有 VID,用来进行字段查询;边结构还分起点 srcId 和终点 dstId,就是上图的两处 VertexID。

如上图所示,这个 Space 中配置的 VID 类型是 String,而 NebulaGraph 支持的 VID 类型有两种:一种是 INT,数值类型,像手机号之类的可以用 INT 来存储;一种是 String,比如说人名之类的,当然你要用 String 来存储像是身份证号之类的数值信息也可以。但是,用 VID 的查询效率从经验看是 INT 类型是远高于用 String 作为 VID 类型的。

回到上面的这个例子,一开始用户创建 VID 时,直接选取了 FIXED_STRING 类型,设定为了 256 位的定长 String。但是这里会导致一个问题:

  • 594,952(点数)*256 (VID 大小)* (1 + 1) + 798,826(边数)* 256(VID 大小) * (2 + 2 + 2 + 2) = 1.80 GB

上面的例子是数据存储的大小计算过程,点的数量乘以定长的长度(这里是 256),再乘以占据的字节大小,以及边的数量乘以对应 VID 的长度,再乘以对应边 VID 占据的空间大小,算出来是 1.8 GB。由此,我们可以想到一个事情:是不是可以精简下 VID 的定长长度,设置一个合理的数值,比如说是 32,那它空间占据量就是:

  • 594,952(点数)*32(VID 大小)* (1 + 1) + 798,826(边数)* 32(VID 大小)* (2 + 2 + 2 + 2) = 0.23 GB

修改 VID 的定长长度之后,整个空间使用量就是之前的 1/8,还是非常可观的一个磁盘容量优化。如果是更多的点和边数据量的话,缩减的磁盘空间会更客观。由此,我们有个建议:VID 的定长长度尽可能短,同理,属性类型设置亦如是

超级节点

图数据库实践中,超级节点是一个比较常遇到的性能问题。那么,什么是超级节点(稠密点)呢?图论给出的解释是:一个点有着超级多的相邻边,相邻边就是出边(从这个点指向另外一个点)或者是入边(某个点指向这个点)。像是社交网络中 KOL、网红大V 之类的人,或是证券市场的热门股票,交通网络中的枢纽站、银行系统中的四大行、互联网中的高流量站点,或者是电商平台的爆款商品,等等都是整个关系网络中的超级节点。一旦查询中有超级节点,查询速率就会变得异常的缓慢,甚至有时候内存都耗尽了,查询结果还没跑出来。

下面就来讲讲,现阶段你要用 NebulaGraph 可以如何解决或是绕开超级节点:

要在建模环节规避掉超级节点的问题,“拆点”是可行的方式之一。如上图左侧所示,在未优化建模之前,A 通过 transfer 边关系连接到 B1、B2,如果 A 频繁的转账,势必会导致它成为一个超级节点。这时候,你可以将 A 拆分成 A1 和 A2,按照某种约定的方式,比如说转账的日期,或者是由单一客户拆分成对公客户、对私客户,从而达到拆点、避开超级节点形成的目的。不过,这里会涉及到一个 VID 变更的问题,将 A 拆分成 A1 和 A2,会导致对应的 VID 发生变化,当然你可以命名 A1 为 A0721,A2 为 A0722,加上日期数字来标识它们。

相对应拆点,还有拆/合边的方式。在两个点之间,有许多同一类型的边,比如说转账关系,这时候,可以根据业务的逻辑来进行判断,比如取最短边、最新边、最大边、最小边等,在一些不需要明细的场景里,只体现关系出来,这样就能提升查询效率。除了合并之外,拆边也是一种方式,如上图右侧所示,两个点之前有非常多的关系,它们都是交易类型,可能有一部分是发红包,有一部分是转账,这时候,你就可以按照拆点的逻辑,将边进行拆解。

此外,还有截断,NebulaGraph 有个配置参数是 max_edge_returned_per_vertex,用来应对多邻边的超级节点问题。比如我现在 max_edge_returned_per_vertex 设置成 1,000,那系统从点 A 出发,遍历 1,000 个点之后就不再遍历了,便将结果返回给系统。这里会存在一个问题,加入 A 和 B1 之间存在 1 千多条边,A 和 B2 存在 3 条边,按照这种遍历 1,000 条边之后就不再遍历的设定,可能返回结果中 A 和 B2 的关系边就不会返回了,因为这个遍历返回是随机的。

其他的话,同相关的社区用户交流,我发现在许多业务场景中,超级节点并没有太大的实际业务价值。这里就要提下“超级节点的检测”,比如:通过度中心性算法(DegreeCentrality)计算出出入度大小,这个图算法 nebula-algorithm 和 nebula-analytics 都支持。当这个算法跑完之后,得到的二维表就能告诉你哪些是超级节点,提早让用户知道哪些点会影响查询效率。

此外,假如现在你有一个已知的超级节点,且不方便处理,那查询的时候就要尽量避免逆向查询,即从这个超级节点出发,查询其他节点。

数据导入

社区用户经常遇到的还有一类问题:数据导入慢的问题。一般新的社区用户都会问:你们的导入性能如何?这时候我们一般会说:导入性能老牛逼了,而且我们是直接用 INSERT 方式导入的,速度贼快,之前遇到最快的是 600MB/s。

这时候用户一般会反问:为什么我测试出来,导入速度没有官方说的那么快。

这里就展开说说如何提升你的数据导入性能。

熟悉 NebulaGraph 的小伙伴都知道,它的底层存储是基于 RocksDB 实现的,而 RocksDB 有 wal_ttl 这么一个配置项,如果你的导入数据量非常大,对应的 wal 日志也会相对应的变大。因此,建议在进行数据导入时,将 wal_ttl 时间设短一点,以防止膨胀的 wal 日志过度地占用磁盘,可以得到及时的清理。此外,就是 Compaction 相关的配置项,主要是 max_subcompactionsmax_background_jobs 这两个参数项,一般建议将其设置为 CPU 核数的一半。而这个一半的参数建议,主要来源于用户的反馈以及一些经验数据,不同的场景还是需要不同的配置,HDD 和 SSD 的配置也有所不同,大家可以后面看着情况进行调试。

除了配置参数之外,在做数据导入之前,建议大家执行下 SHOW HOSTS 操作,查看 leader 是否分布均匀:NebulaGraph 会将数据分为若干个 partition,每个 partition 会随机分布在节点上,理想状态自然是 partition 的 leader 是均匀地分布在各个节点的。假如 leader 分布不均的话,可以执行 BALANCE LEADER 操作,确保其均匀分布。

在工具配置方面,可能就是数据导入的重头戏了,配置你的数据导入工具参数:

  • 配置项 concurrency,表示导入工具连接多少个 graphd(查询)节点,一般设置为导入工具 nebula-importer 所在机器的 CPU 核数;
  • manager.batch,虽然 NebulaGraph 支持你通过 INSERT 来一个个点插入到数据库中,但是这个有些低效。因此,设立了 batch 字段用来将一批数据导入到数据库中,默认参数设置是 128,不过这里要根据你自身的数据特性来进行优化。假如你的属性值很多,那么建议将 batch 调小;反之,将 batch 值调大即可。整个 batch 的大小,建议小于 4MB;
  • manager.readerConcurrency 是数据读取的并发数,即,从数据源读取数据的并发数。默认参数是 50,一般建议设置为 30-50 即可;
  • manager.importerConcurrency,数据读取之后,会根据一定的规则拼接成 batch 块,这里就涉及到这个参数项。manager.importerConcurrency 指的是生成待执行的 nGQL 语句的协程数,一般来说它会设置成 manager.readerConcurrency 字段的 10 倍,默认值是 512;

软件说完了,来说下硬件方面的配置。NebulaGrpah 优先推荐使用 SSD,当然 HDD 也是可以的,不过性能相对会差点。此外,在 data_path 下多配置几块盘,每个路径配置一个盘,这个也是之前的实践经验总结出来的。而机器和机器之间,推荐使用万兆网卡。最后一点是,nebula-importer 之类的导入工具有条件的话尽量单独部署,和集群隔离开,不然的话在一台机器人会存在资源抢占的问题。

软硬件都说完了,剩下就是数据本身的问题。图数据库的定位是关系分析,同此无关的事情,例如:全文搜索(ES 擅长的场景),要看情况是否将该部分数据放入到 NebulaGraph 中。由于 NebulaGraph 进行数据导入时,不存在导入的先后顺序,即点和边一起混合导入,这样设计的好处是,数据无需做预处理,坏处是数据导入之后可能会产生悬挂边,不利于后续的查询。最后要留意起点,或终点为空的数据,或者是异常数据,这些数据在异常处理时很容易一不小心形成超级节点。

查询指南

下面来讲讲如何搞定 NebulaGraph 的查询篇。这里是一些 tips:

  • MATCH 性能比 GO 略慢,但 MATCH 是我们优化的重点。如果没有强性能需求的话,推荐还是尽量使用 MATCH,表达能加丰富之外,它同将要出炉的 ISO GQL(图查询语言)是匹配的;
  • 慎用函数(无法下推),在 NebulaGraph 中并没有将函数下推到 storage。因此,像 src(edge)dst(edge)rank(edge)properties($$) 之类的函数,性能都不如 edge_.srcedge._dstedge._rank$$.tag.prop 这些下推到 storage 的表达;
  • 遇到聚合且需要取属性的情况,先聚合再取属性,因为取属性耗时较长;
  • MATCH 如果只是最后需要返回 count,那么对于 count 的变量最好采用 count(id(v)) 类似的形式,这样会应用到属性裁剪,减少内存消耗;
  • 能不带路径尽量不要带路径,带路径需要进行路径构造,属性裁剪会失效,此外,还会增加很多额外的内存开销。

总的来说,减少模糊、增加确定,越早越好

内存保护试试 Memory Tracker

在 v3.4 版本中,引入的一个大功能是:Memory Tracker,用来保护内存,防止内存占用过大导致的 OOM 问题。

  • 预留内存:memory_tracker_untracked_reserved_memory_mb(默认 50 MB)。Memory Tracker 机制会管理通过 new/delete 申请内存,但进程除了通过此种方式申请内存外,还可能存在其他方式占用的内存;比如通过调用底层的 malloc/free 申请,这些内存通过此 flag 控制,在计算时会扣除此部分未被 track 的内存,所以这里预留了 50 MB;
  • 内存比例:memory_tracker_limit_ratio,就是实际可用内存的比例占用多少的情况下,会限制它再申请使用内存。一般默认是 0.8,就是这个内存占用小于 0.8 的情况下,是可以随意使用内存的;当系统内存占用超过 80% 时,系统便会拒绝掉新的查询语句;
    • 数值范围:(0,1],默认 0.8 且为开启状态。大多数的用户的 storage 和 graph 节点都存在混部情况,这时候就会建议调低 memory_tracker_limit_ratio,顺便说一句,这个参数项是支持在线调整的;
    • 数值配置成 2,则会对其进行动态调整,这个动态分配的内存占用比例可能会不大精准;
    • 数值配置成 3,则关闭 Memory Tracker 功能;

此外,你如果要调试 Memory Tracker 的话,可以开启 memory_tracker_detail_log 来获得调试日志,这个参数项默认是关闭的。

经测试,Memory Tracker 对性能有 1% 左右的影响,但是对于上层为平台类产品或者交互式分析类产品,强烈建议打开。为什么呢?因为上层的业务同学不大了解 NebulaGrpah 运行机制的情况下,容易将服务打满,导致内存爆炸,因此开启这个功能之后,至少能保证系统的稳定运行。

最后,如果动态申请内存时,返回报错 GRAPH_MEMORY_EXCEEDED/STORAGE_MEMORY_EXCEEDED 说明这个内存已经不够用,这条查询语句将不会执行(被杀掉)。

语句调试得用 PROFILE

在任意一条 nGQL 查询语句前面加入 PROFILE,并能得到这条语句的执行计划。

上图一条语句的整个生命周期,Planner 是执行计划(Execution Plan)生成器,它会根据 Validator 校验过、语义合法的查询语法树生成可供执行器(Executor)执行的未经优化的执行计划,而该执行计划会在之后交由 Optimizer 生成一个优化的执行计划,并最终交给 Executor 执行。执行计划由一系列节点(PlanNode)组成。而下图则是一些常见的算子,上图每一个 Plan 节点对应了一个算子:

算子介绍
GetNeighbor根据指定的 vid ,从存储层获取起始点和边的属性
Traverse仅用于 MATCH 匹配 ()-[e:0..n]-() 模式,获取拓展过程中的起始点和边的属性
AppendVerticesMATCH 使用,同算子 Traverse 配合获取点的属性
GetEdge获取边的属性
GetVertices获取点的属性,FETCH PROP 或者 GO 语句中。
ScanEdge全表扫描边,例如 MATCH ()-[e]->() RETURN e LIMIT 3
ScanVertices全表扫描点,例如 MATCH (v) return v LIMIT 3
IndexScanMATCH 语句中找到起始点的索引查询
TagIndexPrefixScanLOOKUP 语句中前缀扫描 LOOKUP ON player where player.name == "Steve Nash" YIELD player.name
TagIndexRangeScanLOOKUP 语句中范围扫描 LOOKUP ON player where player.name > "S" YIELD player.name
TagIndexFullScanLOOKUP 语句中全扫描 LOOKUP ON player YIELD player.name
Filter按条件过滤,例如 WHERE 语句
Project获取上一步算子的列
Dedup去重
LeftJoin合并结果
LIMIT限制输出行数

下面这个是一个例子,我们可以结合例子讲解下。一般来说 PROFILE 会生成一个执行计划,同 EXPLAIN 生成执行计划不同,PROFILE 生成的执行计划中会有相对应的执行时间在里面,比如说下面这张图:

一般来说,我们看执行计划不只是看上下的调用关系,还需要去看里面的具体执行细节:

  • execTime:graphd 的处理时间;
  • totalTime:graphd 算子起到到算子退出时间;
  • total_rpc_time:graphd 调用 storage client 发出请求到接收到请求时间;
  • exec:storaged 的处理时间,同上面的 graphd 处理时间的 execTime
  • total:storage client 接收到 graphd 请求到 storage client 发送请求的时间,即 storaged 本身的处理时间加上序列化和反序列化的时间;

除了查看时间之外,我们还要查看 row 就能看到 graphd 和 storaged 的具体通信量大小。上图有 3 个 Partition,每个 Partition 返回 1 个 limit 1,总共就 3 条数据。

此外,还得查看执行计划中是否包含计算下推:

上面两条查询语句的差异,上面提到过,就是将函数改成其他调用方式,将 properties(edge).degree 改为 follow.degree,很明显地看到计算下推了。

某个功能不支持array

因为产品规划的问题,NebulaGraph 可能有些功能没法直接支持。比如用户反馈的:

当前属性仅支持基本类型 long、string,来构建索引。是否可以支持多值,比如:long[]string[] 来构建索引?

的确目前不支持 array,有什么曲线救国的法子?这里提供一些方法,仅供参考:

  1. 把数组放到 string 里,进行查询时,将数据读取出来进行解析,虽然有点不优雅,但是能解决问题;
  2. 转化成 bitmap,将不同的类型组成 bitmap,虽然导致代码会复杂点,但可以获得比较快的过滤;
  3. 边上的 array 转换成两点之间的平行边,相当于一条边就是一个属性,可以方便地进行属性过滤,当然它会带了额外的边数量增加问题;
  4. 点上的 array 转化成自环边,弊端第 3 种方式,会产生大量自己指向自己的平行边;
  5. 把属性作为 tag,比如我现在有个商品,它在北京、上海、杭州都有仓库,这时候可以将这个货点变成一个 tag 属性,从而方便地对其进行查询。这里需要注意的是,这个方式容易产生超级节点,这里就需要注意避免超级节点的产生。

功能更强了 UDF

用户自定义函数(User-defined Function,UDF),用户可以在 nGQL 中调用函数。与从 nGQL 中调用的内置函数一样,UDF 的逻辑通常扩展或增强了 nGQL 的功能,使其具有 nGQL 没有或不擅长处理的功能。UDF 被定义后可以重复使用。

这里简述下 UDF 的使用过程:

  1. 准备编译环境 & 下载源码:https://docs.nebula-graph.com.cn/3.5.0/4.deployment-and-installation/1.resource-preparations/

  2. 进入到 NebulaGraph 代码仓库,创建 UDF 相关源码文件。当前有两个示意文件 standard_deviation.cpp / standard_deviation.h 可以参考

  3. 编译 UDF

g++ -c -I ../src/ -I ../build/third-party/install/include/ -fPIC standard_deviation.cpp -o standard_deviation.o
g++ -shared -o standard_deviation.so standard_deviation.o
  1. 加载 UDF 至 graphd 服务

编辑 graphd 服务配置文件:打开 /usr/local/nebula/etc/nebula-graphd.conf 文件,添加或修改以下配置项:

#  UDF  C++
--enable_udf=true
#  UDF .so
--udf_path=/home/foobar/dev/nebula/udf/
  1. 重启 graphd
udo /usr/local/nebula/scripts/nebula.service restart graphd
  1. 连接到 graphd 后验证
GO 1 TO 2 STEPS FROM “player100” OVER follow YIELD properties(edge).degree AS d | yield collect($-.d) AS d | yield standard_deviation($-.d)

不过,目前 UDF 有些问题:

  1. so 包位置只支持扫描本地,也就是如果你是分布式集群的话,每个机器上都得有个包;
  2. 函数只在 graphd 层,无法下推到存储;
  3. 暂不支持 Java(性能考虑),未来版本会支持;

待解决的问题

这里罗列下未来的产品可优化点:

  1. 全文索引:v3.4 之前的全文索引功能都不太好用,约束比较多,且有些 bug。v3.4 版本做了精简和优化,更加稳定。但实际上,v3.4 及之前的全文索引功能准确讲并不是真正意义的全文索引,主要是支持前缀搜索、通配符搜索、正则表达式搜索和模糊搜索等。并不支持分词、以及查询的分数,v3.6 版本(即将发布)做了全文索引的优化,重新设计了全文索引功能(可以更好的支持 Neo4j 替换)。不过与原有的全文索引不兼容,需要重建索引;
  2. 关于悬挂边的产生:设计理念,不隐式的对数据进行变更导致(删除点的时候不隐式删除边),当然由此会带来悬挂边和孤儿点的问题,后面这块会考虑进行相关的优化;
  3. 事务的支持,大多数人对 NebulaGraph 的事务需求来源于,他认为 NebulaGraph 是一款 TP 产品,TP 产品是一定具备事务性的,这并非是业务场景的需求。当然,事务这块撇开这种某款产品必须具备的特性之外这点,一些生产链路上面,事务还是一个强需求,因此在后续的开发中也会新增事务特性。

其他问题交流

下面问题整理自本次分享的 QA 部分:

Q:上文提到 VID 的设定,是越短越好。短的 VID 会带来什么后果么?

方扬:VID 理论上是越短越好,没有任何的副作用。不过它的设定是在满足你既有的业务需求,不要出现重复的 VID 情况下,尽可能的短即可;

Q:截断的话,是对返回的数据量做限制,这个返回的话是有序的么?

训焘:目前数据的返回是 random,随即返回的,随机根据你的 range 来返回一些数据量。


谢谢你读完本文 (///▽///)

如果你想尝鲜图数据库 NebulaGraph,记得去 GitHub 下载、使用、(з)-☆ star 它 -> GitHub;和其他的 NebulaGraph 用户一起交流图数据库技术和应用技能,留下「你的名片」一起玩耍呀~

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

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

相关文章

论AI与大数据之间的关系

前言 在21世纪,"AI"和"大数据"已经成为科技领域的热门词汇。它们不仅是创新的代名词,更是现代技术发展的双翼。然而,很多人对于AI与大数据之间的关系仍然停留在表面的理解。本文旨在深入探讨这两者之间的深厚关系&#…

【Python机器学习】实验14 手写体卷积神经网络

文章目录 LeNet-5网络结构(1)卷积层C1(2)池化层S1(3)卷积层C2(4)池化层S2(5)卷积层C3(6)线性层F1(7)线性层F2 …

C# 反编译dll文件,将dll文件转为cs文件

工具名:reflector,可免费使用 工具下载地址使用方法 工具下载地址 下载地址: https://www.red-gate.com/products/reflector/ 使用方法 下载安装; 打开软件 打开dll文件 侧边栏找打刚打开的dll文件,直接就能导…

操作教程|通过1Panel开源Linux面板快速安装DataEase

DataEase开源数据可视化分析工具(dataease.io)的在线安装是通过在服务器命令行执行Linux命令来进行的。但是在实际的安装部署过程中,很多数据分析师或者业务人员经常会因为不熟悉Linux操作系统及命令行操作方式,在安装DataEase的过…

论文及代码详解——Restormer

文章目录 论文详解Overall pipelineMulti-Dconv Head Transposed AttentionGated-Dconv Feed-Forward Network 代码详解 论文:《Restormer: Efficient Transformer for High-Resolution Image Restoration》 代码:https://github.com/swz30/Restormer 论…

LRU淘汰策略执行过程

1 介绍 Redis无论是惰性删除还是定期删除,都可能存在删除不尽的情况,无法删除完全,比如每次删除完过期的 key 还是超过 25%,且这些 key 再也不会被客户端访问。 这样的话,定期删除和堕性删除可能都彻底的清理掉。如果…

Nodejs 第十三章(os)

Nodejs os 模块可以跟操作系统进行交互 var os require("node:os")序号API作用1os.type()它在 Linux 上返回 Linux,在 macOS 上返回 Darwin,在 Windows 上返回 Windows_NT2os.platform()返回标识为其编译 Node.js 二进制文件的操作系统平台的…

AI流程图教程,小白也能轻松画!

流程图是一种图形化的工具,用于展示和描述一个过程中的各个步骤、活动和决策。它通过使用不同的图形符号和箭头表示,清晰地展示了流程的顺序和流动路径。流程图通常用于可视化和沟通复杂的业务流程、系统操作流程或项目流程。它帮助人们更好地理解和分析…

oracle警告日志\跟踪日志磁盘空间清理

oracle警告日志\跟踪日志磁盘空间清理 问题现象: 通过查看排查到alert和tarce占用大量磁盘空间 警告日志 /u01/app/oracle/diag/rdbms/orcl/orcl/alert 跟踪日志 /u01/app/oracle/diag/rdbms/orcl/orcl/trace 解决方案: 用adrci清除日志 确定目…

APSIM模型应用与参数优化、批量模拟

APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物生长模拟模型之一。APSIM模型有Classic和Next Generation两个系列模型,能模拟几十种农作物、牧草和树木的土壤-植物-大气过程,被广泛应用于精细农业、水肥管理、气候变化、粮食安…

Pandas字符串操作的各种方法速度测试

由于LLM的发展, 很多的数据集都是以DF的形式发布的,所以通过Pandas操作字符串的要求变得越来越高了,所以本文将对字符串操作方法进行基准测试,看看它们是如何影响pandas的性能的。因为一旦Pandas在处理数据时超过一定限制&#xf…

Kali 分析和管理网络

查看网络 ifconfig 命令 ┌──(root㉿kali)-[~] # eth0:有线网卡 └─# ifconfig eth0: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.56.128 netmask 255.255.255.0 broadcast 192.168.56.255inet6 fe80::20c:29ff:feb3:7991 prefixlen 64 …

DataFrame.plot函数详解(一)

DataFrame.plot函数详解&#xff08;一&#xff09; 1.函数定义 使用pandas.DataFrame的plot方法绘制图像会按照数据的每一列绘制一条曲线&#xff0c;默认按照列columns的名称在适当的位置展示图例 。 DataFrame.plot(xNone, yNone, kindline, axNone, subplotsFalse, shar…

什么是XGBoost

什么是XGBoost XGBoost是GBDT的优秀版本。XGBoost的整体结构和GBDT一致&#xff0c;都是在训练出一棵树的基础上&#xff0c;再训练下一棵树&#xff0c;预测它与真实分布间的差距&#xff0c;通过不断训练用来弥补差距的树&#xff0c;最终用树的组合实现对真实分布的模拟。 …

怎么把AVI视频转GIF动图?教你几种简单好用方法

将视频转成GIF动图有很多好处。首先&#xff0c;GIF动图可以自动循环播放&#xff0c;这使得它们更易于分享和观看。相比于视频&#xff0c;GIF动图的体积更小&#xff0c;加载速度更快&#xff0c;更利于在社交媒体等平台上分享。此外&#xff0c;GIF动图还可以作为一种有趣的…

【地理图库】世界小麦产量分布

声明&#xff1a;来源网络&#xff0c;仅供学习&#xff01;

Git企业开发控制理论和实操-从入门到深入(二)|Git的基本操作

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总https://blog.csdn.net/yu_cblog/cate…

气传导蓝牙耳机哪款好?推荐几款很不错的气传导耳机

​气传导耳机在音质、舒适度和耐久性方面的表现相当出色&#xff0c;能够满足你的各种需求。然而面对市面上这么多气传导耳机&#xff0c;不知道该如何挑选时&#xff0c;也不用过于担心&#xff0c;我先来安利几款很不错的气传导耳机给大家来参考参考&#xff0c;看看有没有心…

Redis过期数据的删除策略

1 介绍 Redis 是一个kv型数据库&#xff0c;我们所有的数据都是存放在内存中的&#xff0c;但是内存是有大小限制的&#xff0c;不可能无限制的增量。 想要把不需要的数据清理掉&#xff0c;一种办法是直接删除&#xff0c;这个咱们前面章节有详细说过&#xff1b;另外一种就是…

冠达管理:水产、食品检测概念股强势拉升 日本将启动福岛核污染水排海

受日本将发动福岛核污染水排海事情刺激&#xff0c;水产股23日盘中大幅拉升&#xff0c;截至发稿&#xff0c;大湖股份涨停&#xff0c;国联水产涨超6%&#xff0c;獐子岛、百洋股份涨超3%。 核污染防治概念亦走强&#xff0c;截至发稿&#xff0c;中电环保涨超11%&#xff0c;…