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

Hive-优化(语法优化篇)

列裁剪与分区裁剪

在生产环境中,会面临列很多或者数据量很大时,如果使用select * 或者不指定分区进行全列或者全表扫描时效率很低。Hive在读取数据时,可以只读取查询中所需要的列,忽视其他的列,这样做可以节省读取开销(中间表存储开销和数据整合开销)

1.列裁剪:在查询时只读取需要的列。避免select *

2.分区裁剪:在查询中只读取需要的分区。

遵循一个原则:尽量少的读入数据,尽早地数据收敛!

分组聚合优化

Map端聚合

Hive中未经优化的分组聚合,是通过一个MapReduce Job实现的。Map端负责读取数据,并按照分组字段分区,通过Shuffle,将数据发往Reduce端,各组数据在Reduce端完成最终的聚合运算。

Hive对分组聚合的优化主要围绕着减少Shuffle数据量进行,具体做法是map-side聚合。所谓map-side聚合,在Hive的Map阶段开启预聚合,先在Map阶段预聚合,然后在Reduce阶段进行全局的聚合。map-side聚合能有效减少shuffle的数据量,提高分组聚合运算的效率。

通俗理解:假设有张8000w数据表,聚合后30组数据,有10个map,若是没有开启分组聚合,则会map将8000w条数据传给reduce,开启分组聚合后,就会每个map先进行分组,10个map各有30组,再将这30*10组数据从map传给reduce,这样效率就会大大增加

map-side 聚合相关的参数如下:

--启用map-side聚合,一般默认开启

set hive.map.aggr=true;

 默认为开启状态

--用于检测源表数据是否适合进行map-side聚合。检测的方法是:先对若干条数据进行map-side聚合,若聚合后的条数和聚合前的条数比值小于该值,则认为该表适合进行map-side聚合;否则,认为该表数据不适合进行map-side聚合,后续数据便不再进行map-side聚合。

set hive.map.aggr.hash.min.reduction=0.5;

--用于检测源表是否适合map-side聚合的条数。

set hive.groupby.mapaggr.checkinterval=100000;

默认为0.5和10w条

会先从大的数据表内,先抽取10w数据进行检测,判断看(分组后的数据)/10w是否在0.5以下,若是则会启用map的分组聚合

--map-side聚合所用的hash table,占用map task堆内存的最大比例,若超出该值,则会对hash table进行一次flush。

set hive.map.aggr.hash.force.flush.memory.threshold=0.9;

优化案例

示例SQL

hive (default)> set hive.map.aggr=true/false;

explain

select t1.province_id,count(*) as cnt from ds_hive.ch12_order_detail_orc t1

group by t1.province_id

;

开启分组聚合后,执行时间26s左右  application_1716866155638_175450  

关闭分组聚合后,执行时间在60s左右,效率提升了34s  application_1716866155638_175451

由上图的详细执行过程分析可知,开启map聚合后,map输出--reduce接受的数据是340,而关闭map分组聚合后,map数据--reduce接受的数据是8000w条,传输时间大大影响

大致的运行前后的步骤对比:

Count Distinct 的优化

在Hive中,DISTINCT关键字用于对查询结果进行去重,以返回唯一的值。其主要作用是消除查询结果中的重复记录,使得返回的结果集中每个值只出现一次。

具体而言,当你在Hive中使用SELECT DISTINCT时,系统会对指定的列或表达式进行去重操作。尽管Hive中的DISTINCT关键字对于去重查询是非常有用的,但在某些情况下可能存在一些缺点:性能开销、数据倾斜、内存需求等。

group by 操作的具体实现原理

1.map阶段,将group by后的字段组合作为一个key,如果group by单个字段,那么key就一个。将group by之后要进行的聚合操作字段作为值,如果要进行count,则value是赋1;如要sum另一个字段,那么value就是该字段。

2.shuffle阶段,按照key的不同分发到不同的reducer。注意此时可能因为key分布不均匀而出现数据倾斜的问题。这个问题是我们处理数据倾斜比较常规的查找原因的方法之一,也是我们解决数据倾斜的处理阶段。(当执行过程中,出现其他任务都已完成,持续等待一个reudce过程的时候,就看出现了数据倾斜问题)

3.reduce阶段,如果是count将相同key的值累加,如果是其他操作,按需要的聚合操作,得到结果。

distinct 的具体实现,当执行Distinct操作时,Hive会将操作转化为一个MapReduce作业,并按照指定的列进行分组。在Map阶段,每个Mapper会读取输入数据,并将指定的列作为输出的key,然后,通过Shuffle过程将具有相同key的数据发送到同一个Reducer中。

当distinct一个字段时,这里会将group by的字段和distinct的字段组合在一起作为map输出的key,value设置为1,同时将group by的字段定为分区键,这一步非常重要,这样就可以将GroupBy字段作为reduce的key,在reduce阶段,利用mapreduce的排序,输入天然就是按照组合key排好序的。根据分区键将记录分发到reduce端后,按顺序取出组合键中的distinct字段,这时distinct字段也是排好序的。依次遍历distinct字段,每找到一个不同值,计数器就自增1,即可得到count distinct结果。

count(distinct)全局合操作的时候,即使我们设定了reduce task的具体个数,例如set mapred.reduce.tasks=100;hive最终也只会启动一个reducer。这就造成了所有map端传来的数据都在一个tasks中执行,这唯一的Reduce Task需要Shuffle大量的数据,并且进行排序聚合等处理,这使得这个操作成为整个作业的IO和运算瓶颈。

 针对上述说的问题,我们可以修改对应的sql来进行优化, count+group by 或者sum+group by的方案来优化,在第一阶段选出全部的非重复的字段id,在第二阶段再对这些已消重的id进行计数

重到细粒度的(日),再聚合到粗粒度(省份)

(目前测试结果不能完全验证如上理论,暂放,确定后再更新)

-- count(distinct)

select count(distinct province_id) from ds_hive.ch12_order_detail_orc ;

-- 优化版 count + group by 

select count(product_id)
from (select product_id
from ds_hive.ch12_order_detail_orc
group by product_id
)t;

第一阶段我们可以通过增大Reduce的并发数,并发处理Map输出。在第二阶段,由于id已经消重,因此COUNT(*)操作在Map阶段不需要输出原id数据,只输出一个合并后的计数即可。这样即使第二阶段Hive强制指定一个Reduce Task的时候,极少量的Map输出数据也不会使单一的Reduce Task成为瓶颈。

其实在实际运行时,Hive还对这两阶段的作业做了额外的优化。它将第二个MapReduce作业Map中的Count过程移到了第一个作业的Reduce阶段。这样在第一阶Reduce就可以输出计数值,而不是消重的全部id。这一优化大幅地减少了第一个作业的Reduce输出IO以及第二个作业Map的输入数据量。最终在同样的运行环境下优化后的语句可以说是大大提升了执行效率。

Join优化

Hive拥有多种join算法,包括Common Join,Map Join,Bucket Map Join,Sort Merge Buckt Map Join等,下面对每种join算法做简要说明:

Common Join  (完整进行map-reduce阶段)

Common Join是Hive中最稳定的join算法,其通过一个MapReduce Job完成一个join操作。Map端负责读取join操作所需表的数据,并按照关联字段进行分区,通过Shuffle,将其发送到Reduce端,相同key的数据在Reduce端完成最终的Join操作。

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。

整个过程包含Map、Shuffle、Reduce阶段

(1)Map阶段

Step1: 读取源表的数据,Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key;

Step2: Map输出的value为join之后所关心的(select或者where中需要用到的)列;同时在value中还会包含表的Tag信息,用于标明此value对应哪个表;

Step3: 按照key进行排序。

(2)Shuffle阶段

根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中。

(3)Reduce阶段

根据key的值完成join操作,期间通过Tag来识别不同表中的数据。

举个例子:

SELECT t1.stu_id

           ,t1.score

           ,t2.sex

      from ds_hive.ch7_score_info t1

  join ds_hive.ch7_stu_info  t2

        on t1.stu_id=t2.stu_id

;

执行计划如下,完整的common join 会完整的经过map-reduce阶段

 执行过程如下:

JOIN操作涉及合并两个或多个表的数据,以便通过共同的列值将它们关联起来。这样的关联操作在处理大规模数据时可能会面临一些性能挑战,因此有必要进行优化。

性能开销: JOIN操作通常涉及将分布在不同节点上的数据进行合并。在传统的MapReduce执行环境中,这意味着需要进行数据的分发、排序和聚合操作,这些操作都会带来较大的性能开销

Shuffle开销: 在传统的MapReduce中,JOIN操作的Shuffle阶段涉及将相同键的数据合并到一起。这个过程需要大量的网络通信和数据传输,尤其是当数据分布不均匀时。

内存消耗: 处理大规模数据的JOIN操作可能需要大量的内存,特别是在进行排序和合并时。这可能导致内存不足的问题,进而影响性能。

复杂度: JOIN操作可能涉及复杂的计算,特别是在关联多个表或在多列上进行关联时。这增加了查询的复杂性,可能导致较长的执行时间。

Map Join (大表join小表)

Map Join算法可以通过两个只有map阶段的Job完成一个join操作。其适用场景为大表join小表。因为只经map+map阶段,减少了shuffle的处理,reduce的读取和处理过程,从而进行性能优化。若某join操作满足要求,则:

第一个Job会读取小表数据,将其制作为hash table,并上传至Hadoop分布式缓存(本质上是上传至每个执行任务的NodeManager节点本地磁盘)。

第二个Job会先从分布式缓存中读取小表数据,并缓存在Map Task的内存中,然后扫描大表数据,这样在map端即可完成关联操作。

Map Join有两种触发方式,一种是用户在SQL语句中增加hint提示,另外一种是Hive优化器根据参与join表的数据量大小,自动触发。

1)Hint提示

用户可通过如下方式,指定通过map join算法,并且将作为map join中的小表。这种方式已经过时,不推荐使用

hive (default)>

select /*+ mapjoin(ta) */

    ta.id,

    tb.id

from table_a ta

join table_b tb

on ta.id=tb.id

;

2)自动触发

Hive在编译SQL语句阶段,起初所有的join操作均采用Common Join算法实现。

之后在物理优化阶段,Hive会根据每个Common Join任务所需表的大小判断该Common Join任务是否能够转换为Map Join任务,若满足要求,便将Common Join任务自动转换为Map Join任务。

但有些Common Join任务所需的表大小,在SQL的编译阶段是未知的(例如对子查询进行join操作),所以这种Common Join任务是否能转换成Map Join任务在编译阶是无法确定的。

针对这种情况,Hive会在编译阶段生成一个条件任务(Conditional Task),其下会包含一个计划列表,计划列表中包含转换后的Map Join任务以及原有的Common Join任务。最终具体采用哪个计划,是在运行时决定的。大致思路如下图所示:

Map join自动转换的具体判断逻辑如下图所示

参数如下:

--启动Map Join自动转换

set hive.auto.convert.join=true;

--一个Common Join operator转为Map Join operator的判断条件,若该Common Join相关的表中,存在n-1张表的大小总和<=该值,则生成一个Map Join计划,此时可能存在多种n-1张表的组合均满足该条件,则hive会为每种满足条件的组合均生成一个Map Join计划,同时还会保留原有的Common Join计划作为后备(back up)计划,实际运行时,优先执行Map Join计划,若不能执行成功,则启动Common Join后备计划。

set hive.mapjoin.smalltable.filesize=25000000;

--开启无条件转Map Join

set hive.auto.convert.join.noconditionaltask=false;

--无条件转Map Join时的小表之和阈值,若一个Common Join operator相关的表中,存在n-1张表的大小总和<=该值,此时hive便不会再为每种n-1张表的组合均生成Map Join计划,同时也不会保留Common Join作为后备计划。而是只生成一个最优的Map Join计划。

set hive.auto.convert.join.noconditionaltask.size= 20971520;

3)示例SQL

set hive.auto.convert.join=false(true);

explain
SELECT t1.province_id
,count(*) as cnt
from ds_hive.ch12_order_detail_orc t1
join ds_hive.ch12_product_info_orc t3 on t1.province_id=t3.id
group by t1.province_id
;

参数设置为false(未优化):既有map,又有reduce,然后join是在reduce阶段

执行完时间 161s

参数设置为true(优化):第一个map加载本地文件,第二个map进行join

执行时间35s

结论:未开启mapjoin,进行commonjoin,执行时间161s,使用mapjoin,执行时间35s,执行效率大大提升

接着我们再来测试另外一个参数。调整hive.auto.convert.join.noconditionaltask.size参数(小于此设置的表会识别为小表),使其小于t3 表 的大小

set hive.auto.convert.join=true;

--重要,一般企业来调整此参数来决定小表的大小,比如让一些略大于小表阈值的表进行mapjoin

set hive.auto.convert.join.noconditionaltask.size=252300;

explain
SELECT t1.user_id
,t1.create_time
,t3.id
from ds_hive.ch12_order_detail_orc t1
join ds_hive.ch12_product_info_orc t3 on t1.province_id=t3.id
;

--------此类优化用的少

set hive.auto.convert.join.noconditionaltask=false;

set hive.mapjoin.smalltable.filesize= 15230000;

第一个sql,因为设置了.noconditionaltask.size=252300,小于表的大小,最终选择了commonjoin执行,第二遍我们关闭有条件执行,由于smalltable.filesize大于小表只有commonjoin,这时候调大set hive.mapjoin.smalltable.filesize=379000002;让其小表大于smalltable.filesize,这时候最终会选择mapjoin。

Bucket Map Join(大表join大表)

两张表都相对较大,若采用普通的Map Join算法,则Map端需要较多的内存来缓存数据,当然可以选择为Map段分配更多的内存,来保证任务运行成功。但是,Map端的内存不可能无上限的分配,所以当参与Join的表数据量均过大时,就可以考虑采用Bucket Map Join算法。Bucket Map Join是对Map Join算法的改进,其打破了Map Join只适用于大表join小表的限制,可用于大表join大表的场景。

Bucket Map Join的核心思想是:若能保证参与join的表均为分桶表,且关联字段为分桶字段,且其中一张表的分桶数量是另外一张表分桶数量的整数倍,就能保证参与join的两张表的分桶之间具有明确的关联关系,所以就可以在两表的分桶间进行Map Join操作了。这样一来,第二个Job的Map端就无需再缓存小表的全表数据了,而只需缓存其所需的分桶即可。其原理如图所示:

优化条件:

1) set hive.optimize.bucketmapjoin = true;

2) 一个表的bucket数是另一个表bucket数的整数倍

3) bucket列 == join列

4) 必须是应用在map join的场景中

Bucket Map Join不支持自动转换,发须通过用户在SQL语句中提供如下Hint提示,并配置如下相关参数,方可使用。

1)Hint提示

hive (default)>

select /*+ mapjoin(ta) */

    ta.id,

    tb.id

from table_a ta

join table_b tb on ta.id=tb.id;

2)相关参数

--关闭cbo优化,cbo会导致hint信息被忽略

set hive.cbo.enable=false;

--map join hint默认会被忽略(因为已经过时),需将如下参数设置为false

set hive.ignore.mapjoin.hint=false;

--启用bucket map join优化功能

set hive.optimize.bucketmapjoin = true;

Sort Merge Bucket Map Join(大表join大表)

Sort Merge Bucket Map Join(简称SMB Map Join)基于Bucket Map Join。SMB Map Join要求,参与join的表均为分桶表,且需保证分桶内的数据是有序的,且分桶字段、排序字段和关联字段为相同字段,且其中一张表的分桶数量是另外一张表分桶数量的整数倍。

SMB Map Join同Bucket Join一样,同样是利用两表各分桶之间的关联关系,在分桶之间进行join操作,不同的是,分桶之间的join操作的实现原理。Bucket Map Join,两个分桶之间的join实现原理为Hash Join算法;而SMB Map Join,两个分桶之间的join实现原理为Sort Merge Join算法。

Hash Join和Sort Merge Join均为关系型数据库中常见的Join实现算法。Hash Join的原理相对简单,就是对参与join的一张表构建hash table,然后扫描另外一张表,然后进行逐行匹配。Sort Merge Join需要在两张按照关联字段排好序的表中进行,其原理如图所示:

Hive中的SMB Map Join就是对两个分桶的数据按照上述思路进行Join操作。可以看出,SMB Map Join与Bucket Map Join相比,在进行Join操作时,Map端是无需对整个Bucket构建hash table,也无需在Map端缓存整个Bucket数据的,每个Mapper只需按顺序逐个key读取两个分桶的数据进行join即可。

Sort Merge Bucket Map Join有两种触发方式,包括Hint提示和自动转换。Hint提示已过时,不推荐使用。下面是自动转换的相关参数:

--启动Sort Merge Bucket Map Join优化

set hive.optimize.bucketmapjoin.sortedmerge=true;

--使用自动转换SMB Join

set hive.auto.convert.sortmerge.join=true;

两张表都相对较大,除了可以考虑采用Bucket Map Join算法,还可以考虑SMB Join。相较于Bucket Map Join,SMB Map Join对分桶大小是没有要求的。

谓词下推

谓词下推(predicate pushdown)是指,尽量将过滤操作前移,以减少后续计算步骤的数据量。数仓实际开发中经常会涉及到多表关联,这个时候就会涉及到on与where的使用。一般在面试的时候会提问:条件写在where里和写在on有什么区别?

相关参数为:

--是否启动谓词下推(predicate pushdown)优化

set hive.optimize.ppd = true;

示例SQL语句

hive (default)>

explain

SELECT t1.id

,t2.province_name

from ds_hive.ch12_order_detail_orc t1

left join ds_hive.ch12_province_info_orc t2 on t1.province_id=t2.id

where t1.product_num=20 and t2.province_name='江苏'

;

关闭谓词下推优化

--是否启动谓词下推(predicate pushdown)优化

set hive.optimize.ppd = false;

--为了测试效果更加直观,关闭cbo优化

set hive.cbo.enable=false;

--为了测试效果更加直观,关闭mapjoin

set hive.auto.convert.join=false;

通过执行计划可以看到,当我们把谓词下推关闭以后,数据是所有数据关联以后才进行过滤的,这样如果量表数据量大,就大大降低了我们的执行效率

开启谓词下推优化

--是否启动谓词下推(predicate pushdown)优化

set hive.optimize.ppd = true;

--为了测试效果更加直观,关闭cbo优化

set hive.cbo.enable=false;

通过执行计划可以看出,过滤操作位于执行计划中的join操作之前。大大减少了关联的数据量。对整体执行效率有很大提升。

开启谓词执行做关联,优化一下SQL

--是否启动谓词下推(predicate pushdown)优化

set hive.optimize.ppd = true;

--为了测试效果更加直观,关闭cbo优化

set hive.cbo.enable=false;

-- 将where条件里关于t2的过滤放到on条件后

explain
    SELECT t1.id
           ,t2.province_name
      from ds_hive.ch12_order_detail_orc t1
left join ds_hive.ch12_province_info_orc  t2
        on t1.province_id=t2.id and t2.province_name='江苏'
  where t1.product_num=20
;

通过执行计划可以看出,t1和t2过滤操作都位于执行计划中的join操作之前,对俩个表都是先过滤再关联,效率更一步提升。

当我们使用左关联的时候:1.所有条件写在where中,只有左边的条件先过滤;2.当所有条件写在 on 里面只有右边的条件起作用,3.为了可以让条件都起作用,就把左表条件写在where里,右边条件写在 on 里,两者都先过滤

结论:

  1. 对于Join(Inner Join)、Full outer Join,条件写在on后面,还是where后面,性能上面没有区别,join谓词下推都生效,Full outer Join都不生效;
  2. 对于Left outer Join ,右侧的表写在on后面、左侧的表写在where后面,性能上有提高;
  3. 对于Right outer Join,左侧的表写在on后面、右侧的表写在where后面,性能上有提高;

合理选择排序

order by
全局排序,只走一个reducer,当表数据量较大时容易计算不出来,性能不佳慎用,在严格模式下需要加limit

sort by
局部排序,即保证单个reduce内结果有序,但没有全局排序的能力。

distribute by
按照指定的字段把数据划分输出到不同的reducer中,是控制数据如何从map端输出到reduce端,hive会根据distribute by后面的字段和对应reducer的个数进行hash分发

cluster by
拥有distrubute by的能力,同时也拥有sort by的能力,所以可以理解cluster by是 distrubute by+sort by

实例代码优化

-- 优化前
select
id         
,count(*) as cnt
from ds_hive.ch12_order_detail_orc t1
group by id
order by cnt
limit 100
;

执行时间109.9s

-- 优化后
select
id
,cnt
from
(select id       ,count(*) as cntfrom ds_hive.ch12_order_detail_orc t1group by id
) t1
distribute by cnt
sort by id
limit 100
;

执行时间69s

通过优化前后时间对比,可以看到优化效果

注意实际企业运维可以通过参数 set hive.mapred.mode=strict 来设置严格模式,这个时候使用 orderby 全局排序必须加 limit;建议如果不是非要全局有序的话,局部有序的话建议使用 sortby,它会视情况启动多个 reducer 进行排序,并且保证每个 reducer 内局部有序。为了控制map 端数据分配到 reducer 的 key,往往还要配合 distribute by 一同使用。如果不加 distribute by 的话,map 端数据就会随机分配到 reducer。

相关文章:

Hive-优化(语法优化篇)

列裁剪与分区裁剪 在生产环境中&#xff0c;会面临列很多或者数据量很大时&#xff0c;如果使用select * 或者不指定分区进行全列或者全表扫描时效率很低。Hive在读取数据时&#xff0c;可以只读取查询中所需要的列&#xff0c;忽视其他的列&#xff0c;这样做可以节省读取开销…...

C语言100天练习题【记录本】

C语言经典100题&#xff08;手把手 编程&#xff09; 可以在哔哩哔哩找到&#xff08;url:C语言经典100题&#xff08;手把手 编程&#xff09;_哔哩哔哩_bilibili&#xff09; 已解决的天数&#xff1a;一&#xff0c;二&#xff0c;五&#xff0c;六&#xff0c;八&#xf…...

记录排查服务器CPU负载过高

1.top 命令查看cpu占比过高的进程id 这里是 6 2. 查看进程中占用CPU过高的线程 id 这里是9 top -H -p 6 ps -mp 6 -o THREAD,tid,time 使用jstack 工具 产看进程的日志 需要线程id转换成16进制 jstack 6 | grep “0x9” 4.jstack 6 可以看进程的详细日志 查看日志发现是 垃圾回…...

Spring Boot 项目中 Redis 常见问题及解决方案

目录 缓存穿透缓存雪崩缓存击穿Redis 连接池耗尽Redis 序列化问题总结 1. 缓存穿透 问题描述 缓存穿透是指查询一个不存在的数据&#xff0c;由于缓存中没有该数据&#xff0c;请求会直接打到数据库上&#xff0c;导致数据库压力过大。 解决方案 缓存空值&#xff1a;即使…...

基于Spring Boot的校园失物招领系统的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

10 【HarmonyOS NEXT】 仿uv-ui组件开发之Avatar头像组件开发教程(一)

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; 目录 第一篇&#xff1a;Avatar 组件基础概念与设计1. 组件概述2. 接口设计2.1 形状类型定义2.2 尺寸类型定义2.3 组件属性接口 3. 设计原则4. 使用…...

OpenHarmony 5.0.0 Release

OpenHarmony 5.0.0 Release 版本概述 OpenHarmony 5.0.0 Release版本标准系统能力持续完善。相比OpenHarmony 5.0 Beta1&#xff0c;Release版本做出了如下特性新增或增强&#xff1a; 应用框架新增更多生命周期管理能力、提供子进程相关能力&#xff0c;可以对应用运行时的…...

RSA的理解运用与Pycharm组装Cryptodome库

1、RSA的来源 RSA通常指基于RSA算法的密码系统&#xff0c;令我没想到的是&#xff0c;其名字的来源竟然不是某个含有特别意义的单词缩写而成&#xff08;比如PHP&#xff1a;Hypertext Preprocessor(超文本预处理器)&#xff09;&#xff0c;而是由1977年提出该算法的三个歪果…...

Android 多用户相关

Android 多用户相关 本文主要记录下android 多用户相关的adb 命令操作. 1: 获取用户列表 命令: adb shell pm list users 输出如下: Users:UserInfo{0:机主:c13} running默认只有一个用户, id为0 &#xff0c;用户状态为运行 2: 创建新用户 命令&#xff1a; adb shell …...

第三课:异步编程核心:Callback、Promise与Async/Await

Node.js 是一个基于事件驱动的非阻塞 I/O 模型&#xff0c;这使得它非常适合处理高并发的网络请求。在 Node.js 中&#xff0c;异步编程是一项非常重要的技能。理解和掌握异步编程的不同方式不仅能提高代码的效率&#xff0c;还能让你更好地应对复杂的开发任务。本文将深入探讨…...

红果短剧安卓+IOS双端源码,专业短剧开发公司

给大家拆解一下红果短剧/河马短剧&#xff0c;这种看光解锁视频&#xff0c;可以挣金币的短剧APP。给大家分享一个相似的短剧APP源码&#xff0c;这个系统已接入穿山甲广告、百度广告、快手广告、腾讯广告等&#xff0c;类似红果短剧的玩法&#xff0c;可以看剧赚钱&#xff0c…...

C# ArrayPool

ArrayPool<T> 的作用ArrayPool<T> 的使用方式共享数组池自定义数组池 注意事项应用场景 在C#中&#xff0c;ArrayPool<T> 是一个非常有用的工具类&#xff0c;主要用于高效地管理数组的分配和回收&#xff0c;以减少内存分配和垃圾回收的压力。它属于 System…...

Conda 生态系统介绍

引言 Conda 是一个开源的包管理和环境管理系统,最初由 Continuum Analytics 开发,现为 Anaconda 公司维护。它在数据科学和 Python/R 生态中占据核心地位,因其能跨平台(Linux/Windows/macOS)管理依赖关系,并通过虚拟环境隔离不同项目的开发环境。Conda 的生态系统包含多…...

批量将 Word 拆分成多个文件

当一个 Word 文档太大的时候&#xff0c;我们通常会将一个大的 Word 文档拆分成多个小的 Word 文档&#xff0c;在 Office 中拆分 Word 文档是比较麻烦的&#xff0c;我们需要将 Word 文档的页面复制到另外一个 Word 文档中去&#xff0c;然后删除原 Word 文档中的内容。当然也…...

Gravitino源码分析-SparkConnector 实现原理

Gravitino SparkConnector 实现原理 本文参考了官网介绍&#xff0c;想看官方解析请参考 官网地址 本文仅仅介绍原理 文章目录 Gravitino SparkConnector 实现原理背景知识-Spark Plugin 介绍(1) **插件加载**(2) **DriverPlugin 初始化**(3) **ExecutorPlugin 初始化**(4) *…...

react基本功

useLayoutEffect useLayoutEffect 用于在浏览器重新绘制屏幕之前同步执行代码。它与 useEffect 相同,但执行时机不同。 主要特点 执行时机:useLayoutEffect 在 DOM 更新完成后同步执行,但在浏览器绘制之前。这使得它可以在浏览器渲染之前读取和修改 DOM,避免视觉上的闪烁…...

python-leetcode-解决智力问题

2140. 解决智力问题 - 力扣&#xff08;LeetCode&#xff09; 这道题是一个典型的 动态规划&#xff08;Dynamic Programming, DP&#xff09; 问题&#xff0c;可以使用 自底向上 的方式解决。 思路 定义状态&#xff1a; 设 dp[i] 表示从第 i 题开始&#xff0c;能获得的最高…...

引领变革!北京爱悦诗科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!

在2025年“GAS消费电子科创奖”评选中&#xff0c;北京爱悦诗科技有限公司提交的“aigo爱国者GS06”&#xff0c;在技术创新性、设计创新性、工艺创新性、智能化创新性及原创性五大维度均获得评委的高度认可&#xff0c;荣获“产品创新奖”。 这一奖项不仅是对爱悦诗在消费电子…...

微信小程序+SpringBoot的单词学习小程序平台(程序+论文+讲解+安装+修改+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统背景 &#xff08;一&#xff09;社会需求背景 在全球化的大背景下&#xff0c;英语作为国际…...

wordpress分类名称调用的几种情况

在WordPress中&#xff0c;如果你想调用当前分类的名称&#xff0c;可以使用single_cat_title()函数。以下是一些常见的使用方法和场景&#xff1a; 1. 在分类页面调用当前分类名称 如果你正在分类存档页面(category.php)中&#xff0c;可以直接使用single_cat_title()函数来…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...