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

Hive提升篇-Hive修改事务

简介

Hive 默认是不允许数据更新操作的,毕竟它不擅长,即使在0.14版本后,做一些额外的配置便可开启Hive数据更新操作。而在海量数据场景下做update、delete之类的行级数据操作时,效率并不如意。

简单使用

修改HIVE_HOME/conf/hive-site.xml,添加如下配置

<property><name>hive.support.concurrency</name><value>true</value>
</property>
<property><name>hive.exec.dynamic.partition.mode</name><value>nonstrict</value>
</property>
<property><name>hive.txn.manager</name><value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
</property>
<property><name>hive.compactor.initiator.on</name><value>true</value>
</property>
<property><name>hive.compactor.worker.threads</name><value>1</value>
</property>

建表

create table if not exists accountInfo(
id int,
name string,
age int
)
clustered by (id) into 4 buckets 
stored as orc TBLPROPERTIES ('transactional'='true');

建表须知

1 注意存储格式按ORC方式
2 进行数据分桶
3 添加表属性:‘transactional’=‘true’

分发配置到其他hive节点。

测试如下

插入测试数据

在这里插入图片描述

更新数据(此处配置了Hive on Tez)

在这里插入图片描述

数据删除

在这里插入图片描述

hive作为数仓常用技术工具,更多的是用于数据的存储分析,而比较少涉及到数据更新。并且在OLAP场景下并不适合做原有数据更新,更不用说行级别的细粒度操作。记得在一些状态更新场景下会有缓慢渐变维的运用,可即使如此也要运用拉链表保存历史数据,很少将原有数据直接覆盖;你不知道被覆盖的数据蕴含着怎样的价值。

而在一些海量OLTP场景中,也会运用Hbase去替代传统RDB架构;若在运用中伴有大量的数据更新操作,我想Hbase会是不错的选择。


Hive事务原理简介

Apache Hive 0.13 版本引入了事务特性,能够在 Hive 表上实现 ACID 语义,包括 INSERT/UPDATE/DELETE/MERGE 语句、增量数据抽取等。Hive 3.0 又对该特性进行了优化,包括改进了底层的文件组织方式,减少了对表结构的限制,以及支持条件下推和向量化查询。Hive 事务表的介绍和使用方法可以参考 Hive Wiki 和 各类教程,本文将重点讲述 Hive 事务表是如何在 HDFS 上存储的,及其读写过程是怎样的。

文件结构

插入数据

1
2
3
4
5
6
7
CREATE TABLE employee (id int, name string, salary int)
STORED AS ORC TBLPROPERTIES ('transactional' = 'true');INSERT INTO employee VALUES
(1, 'Jerry', 5000),
(2, 'Tom',   8000),
(3, 'Kate',  6000);

INSERT 语句会在一个事务中运行。它会创建名为 delta 的目录,存放事务的信息和表的数据。

1
2
3
/user/hive/warehouse/employee/delta_0000001_0000001_0000
/user/hive/warehouse/employee/delta_0000001_0000001_0000/_orc_acid_version
/user/hive/warehouse/employee/delta_0000001_0000001_0000/bucket_00000

目录名称的格式为 delta_minWID_maxWID_stmtID,即 delta 前缀、写事务的 ID 范围、以及语句 ID。具体来说:

  • 所有 INSERT 语句都会创建 delta 目录。UPDATE 语句也会创建 delta 目录,但会先创建一个 delete 目录,即先删除、后插入。delete 目录的前缀是 delete_delta;
  • Hive 会为所有的事务生成一个全局唯一的 ID,包括读操作和写操作。针对写事务(INSERT、DELETE 等),Hive 还会创建一个写事务 ID(Write ID),该 ID 在表范围内唯一。写事务 ID 会编码到 delta 和 delete 目录的名称中;
  • 语句 ID(Statement ID)则是当一个事务中有多条写入语句时使用的,用作唯一标识。

再看文件内容,_orc_acid_version 的内容是 2,即当前 ACID 版本号是 2。它和版本 1 的主要区别是 UPDATE 语句采用了 split-update 特性,即上文提到的先删除、后插入。这个特性能够使 ACID 表支持条件下推等功能,具体可以查看 HIVE-14035。bucket_00000 文件则是写入的数据内容。由于这张表没有分区和分桶,所以只有这一个文件。事务表都以 ORC 格式存储的,我们可以使用 orc-tools 来查看文件的内容:

1
2
3
4
$ orc-tools data bucket_00000
{"operation":0,"originalTransaction":1,"bucket":536870912,"rowId":0,"currentTransaction":1,"row":{"id":1,"name":"Jerry","salary":5000}}
{"operation":0,"originalTransaction":1,"bucket":536870912,"rowId":1,"currentTransaction":1,"row":{"id":2,"name":"Tom","salary":8000}}
{"operation":0,"originalTransaction":1,"bucket":536870912,"rowId":2,"currentTransaction":1,"row":{"id":3,"name":"Kate","salary":6000}}

输出内容被格式化为了一行行的 JSON 字符串,我们可以看到具体数据是在 row 这个键中的,其它键则是 Hive 用来实现事务特性所使用的,具体含义为:

  • operation 0 表示插入,1 表示更新,2 表示删除。由于使用了 split-update,UPDATE 是不会出现的;
  • originalTransaction 是该条记录的原始写事务 ID。对于 INSERT 操作,该值和 currentTransaction 是一致的。对于 DELETE,则是该条记录第一次插入时的写事务 ID;
  • bucket 是一个 32 位整型,由 BucketCodec 编码,各个二进制位的含义为:
    • 1-3 位:编码版本,当前是 001
    • 4 位:保留;
    • 5-16 位:分桶 ID,由 0 开始。分桶 ID 是由 CLUSTERED BY 子句所指定的字段、以及分桶的数量决定的。该值和 bucket_N 中的 N 一致;
    • 17-20 位:保留;
    • 21-32 位:语句 ID;
    • 举例来说,整型 536936448 的二进制格式为 00100000000000010000000000000000,即它是按版本 1 的格式编码的,分桶 ID 为 1;
  • rowId 是一个自增的唯一 ID,在写事务和分桶的组合中唯一;
  • currentTransaction 当前的写事务 ID;
  • row 具体数据。对于 DELETE 语句,则为 null

我们可以注意到,文件中的数据会按 (originalTransactionbucketrowId) 进行排序,这点对后面的读取操作非常关键。

这些信息还可以通过 row__id 这个虚拟列进行查看:

1
SELECT row__id, id, name, salary FROM employee;

输出结果为:

1
2
3
{"writeid":1,"bucketid":536870912,"rowid":0}    1       Jerry   5000
{"writeid":1,"bucketid":536870912,"rowid":1}    2       Tom     8000
{"writeid":1,"bucketid":536870912,"rowid":2}    3       Kate    6000

增量数据抽取 API V2

Hive 3.0 还改进了先前的 增量抽取 API,通过这个 API,用户或第三方工具(Flume 等)就可以利用 ACID 特性持续不断地向 Hive 表写入数据了。这一操作同样会生成 delta 目录,但更新和删除操作不再支持。

1
2
3
4
5
6
StreamingConnection connection = HiveStreamingConnection.newBuilder().connect();
connection.beginTransaction();
connection.write("11,val11,Asia,China".getBytes());
connection.write("12,val12,Asia,India".getBytes());
connection.commitTransaction();
connection.close();

更新数据

1
UPDATE employee SET salary = 7000 WHERE id = 2;

这条语句会先查询出所有符合条件的记录,获取它们的 row__id 信息,然后分别创建 delete 和 delta 目录:

1
2
3
/user/hive/warehouse/employee/delta_0000001_0000001_0000/bucket_00000
/user/hive/warehouse/employee/delete_delta_0000002_0000002_0000/bucket_00000
/user/hive/warehouse/employee/delta_0000002_0000002_0000/bucket_00000

delete_delta_0000002_0000002_0000/bucket_00000 包含了删除的记录:

1
{"operation":2,"originalTransaction":1,"bucket":536870912,"rowId":1,"currentTransaction":2,"row":null}

delta_0000002_0000002_0000/bucket_00000 包含更新后的数据:

1
{"operation":0,"originalTransaction":2,"bucket":536870912,"rowId":0,"currentTransaction":2,"row":{"id":2,"name":"Tom","salary":7000}}

DELETE 语句的工作方式类似,同样是先查询,后生成 delete 目录。

合并表

MERGE 语句和 MySQL 的 INSERT ON UPDATE 功能类似,它可以将来源表的数据合并到目标表中:

1
2
3
4
5
6
7
8
9
CREATE TABLE employee_update (id int, name string, salary int);
INSERT INTO employee_update VALUES
(2, 'Tom',  7000),
(4, 'Mary', 9000);MERGE INTO employee AS a
USING employee_update AS b ON a.id = b.id
WHEN MATCHED THEN UPDATE SET salary = b.salary
WHEN NOT MATCHED THEN INSERT VALUES (b.id, b.name, b.salary);

这条语句会更新 Tom 的薪资字段,并插入一条 Mary 的新记录。多条 WHEN 子句会被视为不同的语句,有各自的语句 ID(Statement ID)。INSERT 子句会创建 delta_0000002_0000002_0000 文件,内容是 Mary 的数据;UPDATE 语句则会创建 delete_delta_0000002_0000002_0001 和 delta_0000002_0000002_0001 两个文件,删除并新增 Tom 的数据。

1
2
3
4
/user/hive/warehouse/employee/delta_0000001_0000001_0000
/user/hive/warehouse/employee/delta_0000002_0000002_0000
/user/hive/warehouse/employee/delete_delta_0000002_0000002_0001
/user/hive/warehouse/employee/delta_0000002_0000002_0001

压缩

随着写操作的积累,表中的 delta 和 delete 文件会越来越多。事务表的读取过程中需要合并所有文件,数量一多势必会影响效率。此外,小文件对 HDFS 这样的文件系统也是不够友好的。因此,Hive 引入了压缩(Compaction)的概念,分为 Minor 和 Major 两类。

Minor Compaction 会将所有的 delta 文件压缩为一个文件,delete 也压缩为一个。压缩后的结果文件名中会包含写事务 ID 范围,同时省略掉语句 ID。压缩过程是在 Hive Metastore 中运行的,会根据一定阈值自动触发。我们也可以使用如下语句人工触发:

1
ALTER TABLE employee COMPACT 'minor';

以上文中的 MERGE 语句的结果举例,在运行了一次 Minor Compaction 后,文件目录结构将变为:

1
2
/user/hive/warehouse/employee/delete_delta_0000001_0000002
/user/hive/warehouse/employee/delta_0000001_0000002

在 delta_0000001_0000002/bucket_00000 文件中,数据会被排序和合并起来,因此文件中将包含两行 Tom 的数据。Minor Compaction 不会删除任何数据。

Major Compaction 则会将所有文件合并为一个文件,以 base_N 的形式命名,其中 N 表示最新的写事务 ID。已删除的数据将在这个过程中被剔除。row__id 则按原样保留。

1
/user/hive/warehouse/employee/base_0000002

需要注意的是,在 Minor 或 Major Compaction 执行之后,原来的文件不会被立刻删除。这是因为删除的动作是在另一个名为 Cleaner 的线程中执行的。因此,表中可能同时存在不同事务 ID 的文件组合,这在读取过程中需要做特殊处理。

读取过程

我们可以看到 ACID 事务表中会包含三类文件,分别是 basedelta、以及 delete。文件中的每一行数据都会以 row__id 作为标识并排序。从 ACID 事务表中读取数据就是对这些文件进行合并,从而得到最新事务的结果。这一过程是在 OrcInputFormat 和 OrcRawRecordMerger 类中实现的,本质上是一个合并排序的算法。

以下列文件为例,产生这些文件的操作为:插入三条记录,进行一次 Major Compaction,然后更新两条记录。1-0-0-1 是对 originalTransaction - bucketId - rowId - currentTransaction 的缩写。

1
2
3
4
5
6
7
+----------+    +----------+    +----------+
| base_1   |    | delete_2 |    | delta_2  |
+----------+    +----------+    +----------+
| 1-0-0-1  |    | 1-0-1-2  |    | 2-0-0-2  |
| 1-0-1-1  |    | 1-0-2-2  |    | 2-0-1-2  |
| 1-0-2-1  |    +----------+    +----------+
+----------+

合并过程为:

  • 对所有数据行按照 (originalTransactionbucketIdrowId) 正序排列,(currentTransaction) 倒序排列,即:
    • 1-0-0-1
    • 1-0-1-2
    • 1-0-1-1
    • 2-0-1-2
  • 获取第一条记录;
  • 如果当前记录的 row__id 和上条数据一样,则跳过;
  • 如果当前记录的操作类型为 DELETE,也跳过;
    • 通过以上两条规则,对于 1-0-1-2 和 1-0-1-1,这条记录会被跳过;
  • 如果没有跳过,记录将被输出给下游;
  • 重复以上过程。

合并过程是流式的,即 Hive 会将所有文件打开,预读第一条记录,并将 row__id 信息存入到 ReaderKey 类型中。该类型实现了 Comparable 接口,因此可以按照上述规则自定义排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class RecordIdentifier implements WritableComparable<RecordIdentifier> {private long writeId;private int bucketId;private long rowId;protected int compareToInternal(RecordIdentifier other) {if (other == null) { return -1; }if (writeId != other.writeId) { return writeId < other.writeId ? -1 : 1; }if (bucketId != other.bucketId) { return bucketId < other.bucketId ? - 1 : 1; }if (rowId != other.rowId) { return rowId < other.rowId ? -1 : 1; }return 0;}
}public class ReaderKey extends RecordIdentifier {private long currentWriteId;private boolean isDeleteEvent = false;public int compareTo(RecordIdentifier other) {int sup = compareToInternal(other);if (sup == 0) {if (other.getClass() == ReaderKey.class) {ReaderKey oth = (ReaderKey) other;if (currentWriteId != oth.currentWriteId) { return currentWriteId < oth.currentWriteId ? +1 : -1; }if (isDeleteEvent != oth.isDeleteEvent) { return isDeleteEvent ? -1 : +1; }} else {return -1;}}return sup;}
}

然后,ReaderKey 会和文件句柄一起存入到 TreeMap 结构中。根据该结构的特性,我们每次获取第一个元素时就能得到排序后的结果,并读取数据了。

1
2
3
4
5
6
public class OrcRawRecordMerger {private TreeMap<ReaderKey, ReaderPair> readers = new TreeMap<>();public boolean next(RecordIdentifier recordIdentifier, OrcStruct prev) {Map.Entry<ReaderKey, ReaderPair> entry = readers.pollFirstEntry();}
}

选择文件

上文中提到,事务表目录中会同时存在多个事务的快照文件,因此 Hive 首先要选择出反映了最新事务结果的文件集合,然后再进行合并。举例来说,下列文件是一系列操作后的结果:两次插入,一次 Minor Compaction,一次 Major Compaction,一次删除。

1
2
3
4
5
delta_0000001_0000001_0000
delta_0000002_0000002_0000
delta_0000001_0000002
base_0000002
delete_delta_0000003_0000003_0000

过滤过程为:

  • 从 Hive Metastore 中获取所有成功提交的写事务 ID 列表;
  • 从文件名中解析出文件类型、写事务 ID 范围、以及语句 ID;
  • 选取写事务 ID 最大且合法的那个 base 目录,如果存在的话;
  • 对 delta 和 delete 文件进行排序:
    • minWID 较小的优先;
    • 如果 minWID 相等,则 maxWID 较大的优先;
    • 如果都相等,则按 stmtID 排序;没有 stmtID 的会排在前面;
  • 将 base 文件中的写事务 ID 作为当前 ID,循环过滤所有 delta 文件:
    • 如果 maxWID 大于当前 ID,则保留这个文件,并以此更新当前 ID;
    • 如果 ID 范围相同,也会保留这个文件;
    • 重复上述步骤。

过滤过程中还会处理一些特别的情况,如没有 base 文件,有多条语句,包含原始文件(即不含 row__id 信息的文件,一般是通过 LOAD DATA 导入的),以及 ACID 版本 1 格式的文件等。具体可以参考 AcidUtils#getAcidState 方法。

并行执行

在 Map-Reduce 模式下运行 Hive 时,多个 Mapper 是并行执行的,这就需要将 delta 文件按一定的规则组织好。简单来说,base 和 delta 文件会被分配到不同的分片(Split)中,但所有分片都需要能够读取所有的 delete 文件,从而根据它们忽略掉已删除的记录。

向量化查询

当 向量化查询 特性开启时,Hive 会尝试将所有的 delete 文件读入内存,并维护一个特定的数据结构,能够快速地对数据进行过滤。如果内存放不下,则会像上文提到的过程一样,逐步读取 delete 文件,使用合并排序的算法进行过滤。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class VectorizedOrcAcidRowBatchReader {private final DeleteEventRegistry deleteEventRegistry;protected static interface DeleteEventRegistry {public void findDeletedRecords(ColumnVector[] cols, int size, BitSet selectedBitSet);}static class ColumnizedDeleteEventRegistry implements DeleteEventRegistry {}static class SortMergedDeleteEventRegistry implements DeleteEventRegistry {}public boolean next(NullWritable key, VectorizedRowBatch value) {BitSet selectedBitSet = new BitSet(vectorizedRowBatchBase.size);this.deleteEventRegistry.findDeletedRecords(innerRecordIdColumnVector,vectorizedRowBatchBase.size, selectedBitSet);for (int setBitIndex = selectedBitSet.nextSetBit(0), selectedItr = 0;setBitIndex >= 0;setBitIndex = selectedBitSet.nextSetBit(setBitIndex+1), ++selectedItr) {value.selected[selectedItr] = setBitIndex;}}
}

事务管理

为了实现 ACID 事务机制,Hive 还引入了新的事务管理器 DbTxnManager,它能够在查询计划中分辨出 ACID 事务表,联系 Hive Metastore 打开新的事务,完成后提交事务。它也同时实现了过去的读写锁机制,用来支持非事务表的情形。

Hive Metastore 负责分配新的事务 ID。这一过程是在一个数据库事务中完成的,从而避免多个 Metastore 实例冲突的情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class TxnHandler {private List<Long> openTxns(Connection dbConn, Statement stmt, OpenTxnRequest rqst) {String s = sqlGenerator.addForUpdateClause("select ntxn_next from NEXT_TXN_ID");s = "update NEXT_TXN_ID set ntxn_next = " + (first + numTxns);for (long i = first; i < first + numTxns; i++) {txnIds.add(i);rows.add(i + "," + quoteChar(TXN_OPEN) + "," + now + "," + now + ","+ quoteString(rqst.getUser()) + "," + quoteString(rqst.getHostname()) + "," + txnType.getValue());}List<String> queries = sqlGenerator.createInsertValuesStmt("TXNS (txn_id, txn_state, txn_started, txn_last_heartbeat, txn_user, txn_host, txn_type)", rows);}
}

PS: 向量化查询

向量化查询执行是Hive特性,可以大大减少典型查询操作(如扫描,过滤器,聚合和连接)的CPU使用率。一个标准的查询执行系统一次处理一行。这涉及在执行的内部循环中长的代码路径和重要的元数据解释。目前Hive也严重依赖于惰性的反序列化,数据列通过一层对象检查器来识别列类型,反序列化数据并在内部循环中确定合适的表达式例程。这些虚拟方法调用层进一步减慢了处理速度。向量化的查询执行通过一次处理1024行的数据块来简化操作。在块内,每一列都被存储为一个向量(一个基本数据类型的数组)。算术和比较等简单操作是通过在紧密循环中快速迭代向量来完成的,在循环内没有或很少有函数调用或条件分支。这些循环以简化的方式进行编译,使用相对较少的指令,并通过有效地使用处理器流水线和高速缓存存储器,以较少的时钟周期完成每条指令

相关文章:

Hive提升篇-Hive修改事务

简介 Hive 默认是不允许数据更新操作的&#xff0c;毕竟它不擅长&#xff0c;即使在0.14版本后&#xff0c;做一些额外的配置便可开启Hive数据更新操作。而在海量数据场景下做update、delete之类的行级数据操作时&#xff0c;效率并不如意。 简单使用 修改HIVE_HOME/conf/hi…...

PMP项目管理未来的发展与趋势

什么是项目管理&#xff1f;关于项目管理的解释主要是基于国际项目管理三大体系不同的解释及本领域权威专家的解释。 项目管理就是以项目为对象的系统管理方法&#xff0c;通过一个临时性的、专门的柔性组织&#xff0c;对项目进行高效率的计划、组织、指导和控制&#xff0c;以…...

深度学习算法面试常问问题(三)

pooling层是如何进行反向传播的&#xff1f; average pooling&#xff1a; 在前向传播中&#xff0c;就是把一个patch的值取平均传递给下一层的一个像素。因此&#xff0c;在反向传播中&#xff0c;就是把某个像素的值平均分成n份 分配给上一层。 max pooling&#xff1a; 在前…...

GEE学习笔记 八十七:python版GEE动态加载地图方法

在Google Earth Engine的python版API更新后&#xff0c;之前使用folium动态加载地图的代码就不能在正常运行&#xff0c;因为整个Google Earth Engine的地图加载服务的URL发生了更新&#xff0c;所以我们也需要更新相关绘制方法。下面我会讲解一种新的绘制方法&#xff0c;大家…...

第三章 SQL错误信息

文章目录第三章 SQL错误信息SQLCODE 0和100SQLCODE -400检索SQL消息文本第三章 SQL错误信息 下表列出了SQL数字错误代码及其错误消息。这些代码作为SQLCODE变量值返回。 注意&#xff1a;虽然本文档将错误代码列为负值&#xff0c;但JDBC和ODBC客户端始终收到正值。例如&…...

axios中的resolvePromise为什么影响promise状态

axios的取消请求意思很简单&#xff0c;就是在发送请求后不久停止发送请求 本文探讨的是v0.22.0之前的CancelToken API&#xff0c;因为在阅读源码交流的时候发现很多朋友不理解为什么CancelToken中的resolvePromise会影响到实例对象身上的promise状态 即下图所示代码&#xf…...

AWS攻略——创建VPC

文章目录创建一个可以外网访问的VPCCIDR主路由表DestinationTarget主网络ACL入站规则出站规则子网创建EC2测试连接创建互联网网关&#xff08;IGW&#xff09;编辑路由表知识点参考资料在 《AWS攻略——VPC初识》一文中&#xff0c;我们在AWS默认的VPC下部署了一台可以SSH访问的…...

一文搞懂ECU休眠唤醒之利器-TJA1145

前言 首先&#xff0c;小T请教大家几个小小问题&#xff0c;你清楚&#xff1a; 什么是TJA1145吗&#xff1f;你知道休眠唤醒控制基本逻辑是怎么样的吗&#xff1f;TJA1145又是如何控制ECU进行休眠唤醒的呢&#xff1f;使用TJA1145时有哪些注意事项呢&#xff1f; 今天&…...

【Java基础】022 -- Lambda与递归练习

目录 一、Lambda表达式 1、Lambda初体验 2、函数式编程 3、Lambda表达式的标准格式 4、小结 5、Lambda表达式的省略写法 ①、示例代码 ②、小结 6、Lambda表达式的练习 ①、Lambda表达式简化Comparator接口的匿名形式 二、综合练习 1、按照要求进行排序&#xff08…...

技研智联云原生容器化平台实践

作者简介&#xff1a;郑建林&#xff0c;现任深圳市技研智联科技有限公司架构师&#xff0c;技术负责人。多年物联网及金融行业经验&#xff0c;对云计算、区块链、大数据等领域有较深入研究及应用。现主要从事 PaaS 平台建设&#xff0c;为公司各业务产品线提供平台底座如技术…...

订单服务:订单流程

订单流程 订单流程是指从订单产生到完成整个流转的过程&#xff0c;从而行程了一套标准流程规则。而不同的产品类型或业务类型在系统中的流程会千差万别&#xff0c;比如上面提到的线上实物订单和虚拟订单的流程&#xff0c;线上实物订单与 O2O 订单等&#xff0c;所以需要根据…...

Python的有用知识,一共十三个代码片段,确定不来看看吗

前言 之前发过22个小技巧&#xff0c;今天就来分享分享13个非常有用的代码片段 赶紧码住&#xff0c;看看你都了解吗 1.将两个列表合并成一个字典 假设我们在 Python 中有两个列表&#xff0c;我们希望将它们合并为字典形式&#xff0c;其中一个列表的项作为字典的键&#…...

数据结构与算法-数组

前言&#xff1a;几乎所有的编程语言都原生支持数组类型。因为数组是最简单的内存数据结构。创建一个数组&#xff1a;let arr new Array()或let arr new Array(5) // 指定长度或let arr new Array(1,2,3,4,5) // 将数组元素作为参数传给构造函数或let arr [1,2,3,4,5] // …...

PMP证书在哪个行业比较有用?

PMP 各个行业都能用&#xff0c;PMP 的知识体系是通用的&#xff0c;管理层的考试也有借鉴PMP知识的地方。历年考生考的最多的是IT 行业&#xff0c;其他行业也都有分布。PMP认证从国外引进大陆这么多年了&#xff0c;其火热程度依然不减&#xff0c;我个人认为是取决于市场的运…...

Wine零知识学习4 —— Wine编译进阶详解

本系列第3篇文章Wine零知识学习3 —— Winetricks介绍及下载和运行讲述了Wentricks的下载及使用。在Winetricks的使用过程中会发现很多应用下载会出现问题&#xff0c;会提示32位程序无法运行在64位系统上。为什么会出现这个问题&#xff1f;又如何解决此问题&#xff1f;这就是…...

win10-右键打开windows terminal

文章目录windows terminal设置右键打开打开注册表添加一个右键选项新建一个项添加右键的名称和图标右键选项执行的命令测试windows terminal windows 新一代命命令行 设置右键打开 打开注册表 WinR 输入&#xff1a; regedit 定位&#xff1a; 计算机\HKEY_CLASSES_ROOT\Di…...

关于使用CMT2300A FIFO缓存区间设置为64Byte的问题

首先请看&#xff0c;CMT2300A 是什么产品&#xff0c;或者说是 模组吗&#xff1f; 请看介绍&#xff1a; https://blog.csdn.net/sishuihuahua/article/details/105095994 以及RFPDK 的使用: 这博客&#xff0c;记录了 RFPDK 的使用,以及遇到的一些问题 我说一下&#…...

网页概念、常用浏览器及内核、Web标准

网页、常用浏览器及内核、Web标准一、网页1.1、什么是网页&#xff1f;1.2、什么是HTML?&#xff08;重点&#xff09;1.3、网页的形成&#xff1f;二、常用浏览器三、浏览器内核四、Web标准&#xff08;重点&#xff09;4.1 为什么需要Web标准&#xff1f;4.2 Web标准的构成一…...

【刷题笔记】--搜索二维矩阵 II

题目&#xff1a; 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16…...

uni-app实战教程

一、准备 下载HBuilderX编辑器&#xff0c;前往下载注册百度AI账号&#xff0c;创建应用获得Appid和Secret 前往注册百度AI通用物体识别文档 前往查阅Uni-App文档 前往查阅HTML5 文档 前往查阅HTML5文档 前往查阅 二、介绍 开发工具&#xff1a;HBuilderX跨段框架&#xff0…...

SpringCloud: sentinel降级配置、热点参数、系统规则 配置到nacos

一、application.yml spring.cloud.sentinel cloud:nacos:discovery:# 服务注册地址server-addr: xxx.xxx.xxx.xxx:8848sentinel:eager: truetransport:# 控制台地址dashboard: localhost:9999# nacos配置持久化datasource:ds2:nacos:server-addr: xxx.xxx.xxx.xxx:8848dataId…...

交换机之配置netsflow

网络监测技术Sflow——提供完整的第二层到第四层信息&#xff0c;可以适应超大网络流量环境下的流量分析&#xff0c;让用户详细、实时地分析网络传输流的性能、趋势和存在的问题。 &#xff08;1&#xff09;特性&#xff1a; 支持在千兆戒更高速的网络上精确地监控网络流量…...

非科班出身学习软件测试可以么

IT行业里对小白最友好的非软件测试莫属了&#xff0c;但是也要看你个人在学习软件测试这件事上面花费了多少的时间和努力了~ 每年毕业季&#xff0c;IT行业依然是比较热门且收入是最高的行业。对于应届毕业生来说想要进入IT行业&#xff0c;除了前后端开发&#xff0c;软件测试…...

面试已上岸,成功拿到阿里和腾讯的入职offer,Java程序员面经全在这了,希望能帮到你!

前言 一开始的时候简历海投大多数都被拒绝了&#xff0c;后来自己找在腾讯上班的朋友帮忙改了一下简历&#xff0c;果然不一样了大多都能拿到面试机会&#xff0c;当然拿到后也没有那么顺利&#xff0c;面了差不多有十几家公司的样子&#xff0c;大大小小的都有&#xff0c;其中…...

Redisson分布式锁

目录一&#xff0c;场景说明二&#xff0c;Redisson分布式锁1&#xff0c;引入依赖2&#xff0c;生成RedissonClient对象3&#xff0c;测试三&#xff0c;说明一&#xff0c;场景说明 为什么需要分布式锁呢&#xff1f; 如果是单机服务&#xff0c;即只有一台服务器&#xff…...

LOF(Local Outlier Factor)原理

文章目录1定义2 k近邻距离&#xff08;k-distance of an object p&#xff09;3 k近邻4 可达距离5 局部可达密度6 lof参考&#xff1a;1定义 LOF&#xff08;Local Outlier Factor&#xff09;是一种描述异常值的方法。 2 k近邻距离&#xff08;k-distance of an object p&am…...

[ vulhub漏洞复现篇 ] Drupal<7.32 Drupalgeddon SQL注入漏洞(CVE-2014-3704)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…...

Part 4 描述性统计分析(占比 10%)——下

文章目录【后续会持续更新CDA Level I&II备考相关内容&#xff0c;敬请期待】【考试大纲】【考试内容】【备考资料】【扩展知识】4、相关分析4.1、相关分析的描述——散点图4.2、相关分析的类型4.3、相关分析的度量4.3.1、协方差4.3.2、相关系数【后续会持续更新CDA Level …...

【一般人不会告诉你】比肩chatgtp的5款AI网站

话不多说&#xff0c;直接上连接 1. Dall-E: https://labs.openai.com/ 2. Codeformer: https://shangchenzhou.com/projects/Co... 3. Playground AI: https://playgroundai.com/ 4. Clip Drop: https://clipdrop.co/relight 5. Astria: https://www.strmr.com/examples …...

LA@相似方阵和对角化

文章目录相似方阵相似矩阵和特征值小结方阵相似对角化结论推论对角化方法归纳例方阵高次幂相似方阵 对角阵是矩阵中最简单的一类矩阵 对角阵相关的乘法运算是很高效的相似方阵是和对角阵相关的概念 设A和B是n阶方阵,如果存在n阶可逆方阵P,使得P−1APBP^{-1}APBP−1APB,则称方阵…...

摄像网站建设/广告收益平台

http://www.microsoft.com/china/msdn/events/featureevents/2004/SmartClientSeminar/index.aspx都是有视频的&#xff01;可惜说话不是很普通话&#xff01;转载于:https://www.cnblogs.com/LearnSap/archive/2004/12/02/71876.html...

微信公众号网站导航怎么做/天津网站排名提升多少钱

我们团队开发了一些小巧有用的工具来满足客户的某些特殊需求。现在我们把这些工具广而告之&#xff0c;希望对大家能有用。说明一下&#xff0c;这些工具不是产品的功能&#xff0c;风险自担。基于Horizon虚拟桌面的盲水印更改全屏虚拟桌面的分辨率清除空闲的horizon桌面会话Wr…...

网页微博怎么用qq登录/太原百度网站快速优化

JavaScript中本地对象、内置对象和宿主对象 1、本地对象 ECMA-262 把本地对象&#xff08;native object&#xff09;定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。 再来看一下&#xff0c;“本地对象”包含哪些内容&#xff1a; Object、Function、Array、String、…...

做母婴的网站有哪些/怎么制作网站教程步骤

六个例子彻底理解finally语句块 这篇博客主要弄清楚两个问题 1. finally块中的代码是否一定会执行 2. finally块中的代码什么时候被执行 首先开始第一个: finally块中的代码一定会被执行么? 答案是否定的,主要有以下几种情况: 1.try之前发生异常或者直接结束的情况. final…...

什么网站可以做会计题目/百度应用平台

不称深度指南&#xff0c;只愿浅度指北之前&#xff0c;用 VBA 开发了一个 Excel 插件「浅北表格助手」&#xff0c;随后&#xff0c;也发了两篇关于WordVBA 的教程&#xff0c;后台有小伙伴留言&#xff0c;说希望看到一些偏实用的代码。今天&#xff0c;它来了。我们在写 Wor…...

网站开发后端 书/排超最新积分榜

Day1 题目描述 计算字符串最后一个单词的长度&#xff0c;单词以空格隔开。 输入描述: 一行字符串&#xff0c;非空&#xff0c;长度小于5000。 输出描述: 整数N&#xff0c;最后一个单词的长度。 示例1 输入 hello world 输出 5 #include <iostream> #inclu…...