【大数据】Doris 数据库与表操作语法实战详解

news2024/10/3 22:50:07

目录

 一、前言

二、数据库基本操作

2.1 修改账户密码

2.2 创建新用户

2.3 创建数据库与账户授权

2.3.1 数据库创建补充说明

2.3.2 数据库账户赋权

三、数据表基本操作

3.1 Doris 数据表介绍与使用

3.1.1 建表结构说明

3.1.2 建表语法与操作

3.1.3 建表示例 - 单分区

3.1.4 建表示例 - 多分区

3.2 单分区与多分区使用场景

3.2.1 单分区使用场景

3.2.2 多分区使用场景

四、Doris 数据导入操作实践

4.1 导入数据方式总结

4.2 insert into

4.2.1 基本语法

4.2.2 操作演示

4.3 Stream load

4.4 Broker load

4.5 Routine Load

4.5.1 准备kafka环境

4.5.2 创建一张测试表

4.5.3 发送几条消息到kafka

4.5.4 创建导入作业

五、数据删除

5.1 删除语法

5.2 操作演示

5.2.1 删除语法补充说明

六、写在文末


 一、前言

对于学习任何一门数据库来说,不管是关系型数据库mysql,还是诸如hive这样的大数据相关的分析性数据库等,只有掌握了数据库操作的基本知识,才能在后续的学习中更加游刃有余,本篇将详细介绍Doris 中数据库和表相关的基础操作。

二、数据库基本操作

在日常使用mysql操作数据库时,为确保数据安全,通常不会直接使用root账户连接和操作,而是由管理员为使用者创建新的账户和密码,并赋予一定的操作权限。

2.1 修改账户密码

Drois环境安装完成之后,内置了 root 和 admin 用户,密码默认都为空,启动完 Doris 程序之后,可以通过 root 或 admin 用户连接到 Doris 集群,在上一篇的环境搭建中,进入容器之后,使用下面的命令登录:

/opt/mysql-5.7.22-linux-glibc2.12-x86_64/bin/mysql -uroot -P9030 -h127.0.0.1 --skip-ssl

如果需要修改root账户密码,执行下面的命令

SET PASSWORD FOR 'root' = PASSWORD('你设置的密码');

2.2 创建新用户

使用下面的命令创建一个新的账户

CREATE USER 'user01' IDENTIFIED BY 'user01';

下次登录的时候,就可以使用上述这个账户进行登录了

mysql -h 主机名称 -P9030 -uuser01 -puser01

注意:

新创建的普通用户默认没有任何权限,还需根据实际需要进行赋权

2.3 创建数据库与账户授权

初始创建数据库时可以通过root或admin账户进行创建,比如下面创建一个新的测试数据库

CREATE DATABASE doris_db;

2.3.1 数据库创建补充说明

与很多中间件一样,如果你不清楚具体语法,可以使用help + command的方式进行查看,比如想要了解如何创建数据库,就可以执行: HELP CREATE DATABASE; 就能看到完整的建库语法

information_schema数据库说明:

  • information_schema是为了兼容MySQL协议而存在,实际中信息可能不是很准确,所以关于具体数据库的信息建议通过直接查询相应数据库而获得。

2.3.2 数据库账户赋权

有了数据库和账户之后,就可以对账户赋权,比如将上述的doris_db赋权给user01,授权之后采用 test 账户登录就可以操作 doris_db数据库了

GRANT ALL ON doris_db TO user01;

然后使用客户端工具登录该账户就能看到数据库了

三、数据表基本操作

3.1 Doris 数据表介绍与使用

在 Doris 中,数据都以表(Table)的形式进行逻辑上的描述。Doris 支持两种类型的表:

  • OLAP 表:主要用于存储静态数据,支持更新和删除操作。

  • 外部表:主要用于临时存储数据,不支持更新和删除操作,通常用于导入数据后再转换为 OLAP 表。

3.1.1 建表结构说明

在 Doris 中创建表时,需要定义表的结构,包括列的定义和约束。

列定义

列定义包括列名、数据类型、是否为空(NULL 或 NOT NULL)等属性。Doris 支持多种数据类型,包括但不限于:

  • 整形类型:TINYINT, SMALLINT, INT, BIGINT

  • 浮点类型:FLOAT, DOUBLE

  • 字符串类型:VARCHAR, CHAR

  • 日期时间类型:DATE, DATETIME

  • JSON 类型:JSON

  • 固定长度二进制类型:FIXED_STRING

主键约束

Doris 支持定义主键(Primary Key),主键用于唯一标识表中的每一行数据。主键可以由单个列或多个列组合而成。定义主键有助于提高查询性能,尤其是对于需要频繁进行更新和删除操作的场景。

分区键

除了主键之外,Doris 还支持分区键(Partition Key),用于将数据逻辑上分割成多个分区,从而提高查询效率。分区键可以是单个列或多个列的组合。

分区

分区是 Doris 中的一个重要特性,用于将大数据集划分为多个较小的部分,以便更快地执行查询。Doris 支持以下几种分区策略:

  • 范围分区(Range Partitioning):根据数值或日期类型的数据范围进行分区。

  • 列表分区(List Partitioning):根据离散的值列表进行分区。

  • Hash 分区:根据哈希函数的结果进行分区。

副本

为了提高数据的可靠性和查询性能,Doris 支持为数据创建多个副本。副本是数据在不同 Backend (BE) 节点上的冗余拷贝,可以提高数据的可用性和容错能力。

3.1.2 建表语法与操作

使用 CREATE TABLE 命令可以建立一个表(Table),也可以通过 HELP CREATE TABLE查看完整的建表语法

HELP CREATE TABLE;

建表完整语法:

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [database.]table_name
    (column_definition1[, column_definition2, ...]
    [, index_definition1[, ndex_definition12,]])
    [ENGINE = [olap|mysql|broker|hive]]
    [key_desc]
    [COMMENT "table comment"];
    [partition_desc]
    [distribution_desc]
    [rollup_index]
    [PROPERTIES ("key"="value", ...)]
    [BROKER PROPERTIES ("key"="value", ...)]

说明:

  • Doris 的建表是一个同步命令,命令返回成功,即表示建表成功。

  • Doris 支持支持单分区复合分区两种建表方式。

    • 单分区:只做 HASH 分布,即只分桶

    • 复合分区:既有分区也有分桶

      • 第一级称为 Partition,即分区。用户可以指定某一维度列作为分区列(当前只支持整型和时间类型的列),并指定每个分区的取值范围。

      • 第二级称为 Distribution,即分桶。用户可以指定一个或多个维度列以及桶数对数据进行 HASH 分布。

3.1.3 建表示例 - 单分区

建立一个名字为 t_user01的逻辑表。分桶列为 siteid,桶数为 10

CREATE TABLE t_user01
(
    siteid INT DEFAULT '10',
    citycode SMALLINT,
    username VARCHAR(32) DEFAULT '',
    pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(siteid, citycode, username)
DISTRIBUTED BY HASH(siteid) BUCKETS 10
PROPERTIES("replication_num" = "1");

参数说明:

  • AGGREGATE KEY,聚合字段,这里根据siteid, citycode, username三个字段进行聚合;

  • DISTRIBUTED,分区的字段,这里分区字段为siteid取hash之后分到10个桶中;

  • PROPERTIES,副本数量的设置,可以根据你的集群数量进行设置;

插入几条数据,通过结果不难看出,前两条数据的pv经过聚合之后存储的结果是一条

insert into t_user01 values(1,1,'user1',10); 
insert into t_user01 values(1,1,'user1',10); 
insert into t_user01 values(1,2,'user1',10);

也可以通过控制台,查看分区相关的详细信息

3.1.4 建表示例 - 多分区

使用下面的sql创建一个多分区的表t_user02,在这里使用event_day 列作为分区列,建立3个分区: p202106,p202107,p202108,每个分区使用 siteid 进行哈希分桶,桶数为10,副本数为1

  • p202106:范围为 [最小值, 2021-07-01)

  • p202107:范围为 [2021-07-01, 2021-08-01)

  • p202108:范围为 [2021-08-01, 2020-09-01)

  • 区间为左闭右开;

CREATE TABLE t_user02
(
    event_day DATE,
    siteid INT DEFAULT '10',
    citycode SMALLINT,
    username VARCHAR(32) DEFAULT '',
    pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(event_day, siteid, citycode, username)
PARTITION BY RANGE(event_day)
(
    PARTITION p202106 VALUES LESS THAN ('2021-07-01'),
    PARTITION p202107 VALUES LESS THAN ('2021-08-01'),
    PARTITION p202108 VALUES LESS THAN ('2021-09-01')
)
DISTRIBUTED BY HASH(siteid) BUCKETS 10
PROPERTIES("replication_num" = "1");

插入几条数据

insert into t_user02 values ('2021-06-03',9,1,'jack',3);
insert into t_user02 values ('2021-06-10',10,2,'rose',2);
insert into t_user02 values ('2021-07-03',11,1,'jim',2);
insert into t_user02 values ('2021-07-05',12,1,'grace',2);
insert into t_user02 values ('2021-07-12',13,2,'tom',2);
insert into t_user02 values ('2021-08-15',14,3,'bush',3);
insert into t_user02 values ('2021-08-12',15,3,'helen',3);

也可以通过控制台 dbs进行详细的查看

在这里列举了表的详细信息,比如分区信息

3.2 单分区与多分区使用场景

3.2.1 单分区使用场景

虽然单分区在某些场景下可能不如多分区那样高效,但它仍然有其适用的场景。下面介绍了单分区在 Apache Doris 中的一些使用场景。

  • 小型数据集

    • 当数据集较小且不需要频繁进行按时间范围或其他条件的过滤查询时,可以使用单分区。这种情况下,单分区可以简化数据管理和查询逻辑。

  • 不需要时间分割的数据

    • 对于那些不需要按时间范围进行查询的数据集,单分区可以避免不必要的分区开销。例如,一些统计汇总表可能只需要定期更新数据,而不涉及历史数据的查询。

  • 全表扫描

    • 在某些情况下,查询需要对整个表进行全表扫描。此时,单分区可以简化查询逻辑,避免分区选择带来的额外复杂性。

  • 简化数据导入

    • 对于不需要按照特定维度(如时间)进行分区的数据集,单分区可以简化数据导入过程。例如,如果数据是从多个来源一次性导入的,且不需要根据时间或其他维度进行拆分,那么单分区可以减少数据导入的复杂度。

  • 存储非时间序列数据

    • 当数据不是按照时间序列组织的,而是根据其他维度(如地理位置、用户ID等)进行查询时,单分区可能更为合适。例如,一个存储用户信息的表可能不需要按时间进行分区,而是直接存储所有用户的信息。

  • 数据量不大且增长缓慢

    • 如果数据量不大且增长速度较慢,单分区可以有效减少管理成本。在这种情况下,多分区的优势并不明显,反而会增加管理复杂度。

  • 实时查询场景

    • 对于需要快速响应的实时查询场景,单分区可以减少分区选择所带来的延迟。虽然多分区可以提高查询性能,但对于非常小的数据集而言,单分区的查询速度已经足够快。

  • 测试开发使用

    • 在测试和开发环境中,为了简化数据管理和测试流程,可以使用单分区。这样可以更快地进行数据加载和查询测试,而无需担心分区逻辑的影响。

  • 特定的聚合查询

    • 如果查询主要是针对整个数据集的聚合操作(如求和、平均值等),单分区可以避免分区选择带来的额外开销。例如,一个用于计算总体统计数据的表可能只需要单分区。

3.2.2 多分区使用场景

复合分区(Composite Partitioning)指的是在一个表中同时使用两种或更多种不同的分区策略。这种分区方式可以更加灵活地满足不同的查询需求和数据管理需求。以下是复合分区的一些常见使用场景:

  • 多维度查询优化

    • 当数据集需要根据多个维度进行高效的查询时,复合分区可以显著提升查询性能。例如,数据可以按照时间维度和业务维度(如地区、用户组等)进行分区,从而支持快速的时间段和业务维度组合查询。

  • 数据生命周期管理

    • 复合分区可以帮助更好地管理不同生命周期阶段的数据。例如,数据可以根据时间进行范围分区,再根据业务标识(如用户ID、设备ID等)进行哈希分区,这样可以方便地管理每个时间段内的不同业务数据。

  • 提高查询效率

    • 通过复合分区,可以将数据分布得更加均匀,减少查询时的数据扫描范围。例如,一个表可以按照时间范围分区,然后再按照某些散列字段(如用户ID)进行哈希分区,这样可以确保数据在集群中分布均匀,并且查询时可以快速定位到相关数据。

  • 并行处理

    • 复合分区可以更好地支持并行处理,特别是在大规模数据集的情况下。通过将数据按照多个维度进行分区,可以在查询时并行处理不同的分区,从而加速查询响应时间。

  • 数据隔离

    • 复合分区还可以帮助实现数据隔离,特别是在多租户环境中。例如,数据可以按照租户ID进行哈希分区,然后在每个租户的数据基础上再按照时间范围进行分区,这样可以确保不同租户的数据不会相互干扰。

  • 数据分布均衡

    • 在分布式数据库环境中,合理的数据分布可以避免热点问题。通过复合分区,可以确保数据在各个节点之间分布得更加均匀,避免某些节点负载过高。

  • 维度表和事实表的关联优化

    • 在数据仓库设计中,复合分区可以用于优化维度表和事实表之间的关联查询。例如,事实表可以按照时间范围分区,再按照维度表中的主键进行哈希分区,从而加快事实表与维度表的连接操作。

  • 实现细粒度访问控制

    • 通过复合分区,可以实现更加细粒度的数据访问控制。例如,数据可以按照部门进行哈希分区,再按照时间范围进行分区,这样可以针对不同部门的数据实施不同的访问策略。

  • 提升写入性能

    • 在需要频繁写入数据的场景中,复合分区可以提高写入性能。通过将数据按照时间范围和业务标识进行分区,可以确保写入操作分散到多个分区,减少单一分区的压力。

  • 支持复杂查询

    • 对于复杂的分析查询,复合分区可以提供更好的支持。例如,复合分区可以帮助实现多表连接、多条件筛选等操作,使得查询更加高效。

四、Doris 数据导入操作实践

Doris 提供了多种数据导入的方式,在实际应用中,业务主要是基于Doris的具体的数据表数据进行数据消费,因此需要将数据提前插入到表中,而上文中演示的insert into 只是其中的一种方式,接下来介绍下相关的数据导入方式。

4.1 导入数据方式总结

为适配不同的数据导入需求,Doris 系统提供了6种不同的导入方式。每种导入方式支持不同的数据源,存在不同的使用方式(异步,同步)。所有导入方式都支持 csv 数据格式。其中 Broker load 还支持 parquet 和 orc 数据格式。

  • Stream load

    • 用户通过 HTTP 协议提交请求并携带原始数据创建导入。主要用于快速将本地文件或数据流中的数据导入到 Doris,导入命令同步返回导入结果。

  • Insert

    • 类似 MySQL 中的 Insert 语句,Doris 提供 INSERT INTO tbl SELECT ...; 的方式从 Doris 的表中读取数据并导入到另一张表。或者通过 INSERT INTO tbl VALUES(...); 插入单条数据。

  • Broker load

    • 通过 Broker 进程访问并读取外部数据源(如 HDFS)导入到 Doris。用户通过 Mysql 协议提交导入作业后,异步执行。通过 SHOW LOAD 命令查看导入结果。

  • Multi load

    • 用户通过 HTTP 协议提交多个导入作业。Multi Load 可以保证多个导入作业的原子生效。

  • Routine load

    • 用户通过 MySQL 协议提交例行导入作业,生成一个常驻线程,不间断的从数据源(如 Kafka)中读取数据并导入到 Doris 中。

  • 通过S3协议导入

    • 用户通过S3协议直接导入数据,用法和Broker Load 类似

4.2 insert into

和操作mysql表类似,这是一种最基本的数据导入方式,doris支持mysql协议,所以可以直接使用这种方式快速插入数据。比如上文中演示的往t_user01插入数据:

insert into t_user01 values(1,1,'user1',10); 
insert into t_user01 values(1,1,'user1',10); 
insert into t_user01 values(1,2,'user1',10);

4.2.1 基本语法

Insert Into 语句的使用方式和 MySQL 等数据库中 Insert Into 语句的使用方式类似。但在 Doris 中,所有的数据写入都是一个独立的导入作业。

完整格式:

INSERT INTO table_name [partition_info] [WITH LABEL label名称] [col_list] [query_stmt] [values];

常用格式【开发测试使用】:

INSERT INTO tbl (col1, col2, ...) VALUES (1, 2, ...), (1,3, ...);

4.2.2 操作演示

在实际工作中,使用 INSERT INTO tbl SELECT ... 这种方式比较多,在学习mysql的时候也有类似的用法,下面演示下使用过程,首先创建一张表,该表与上一步的案例中表一模一样,只是表名称不同

create table user_kafka_copy(
	id int,
	name varchar(50),
	age int
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 10
PROPERTIES("replication_num" = "1");

使用下面的sql插入数据到user_kafka_copy

  • with label label_copy ,即给当前的执行任务加一个标签,方便后续任务失败时可以追溯

insert into user_kafka_copy with label label_copy select * from user_kafka;

执行成功后检查下数据已经导入了

4.3 Stream load

使用下面的命令进行导入

curl --location-trusted -u root:123456 -H "label:user01_20210210" -H "column_separator:," -T user01.csv http://127.0.0.1:8030/api/doris_db/t_user01/_stream_load

参数说明:

  • -H "label:user01_20210210"

    • 指定导入数据的标签;

  • -H "column_separator:,"

    • 指定导入的数据字段之间的分隔符

  • -T user01.csv

    • 指定导入时使用的数据文件

user01.csv内容如下:

执行上面的数据导入命令

可以看到,已经按照预期进行导入并做数据聚合操作

4.4 Broker load

Broker load是一个导入的异步方式,不同的数据源需要部署不同的 broker 进程。可以通过 show broker 命令查看已经部署的 broker。参考文档:按方式导入 - Broker Load - 《Apache Doris v1.2 中文文档》 - 书栈网 · BookStack

4.5 Routine Load

支持用户提交一个常驻的导入任务,通过不断的从指定的数据源读取数据,将数据导入到 Doris 中,当前仅支持kafka系统进行例行导入。

支持无认证的 Kafka 访问,以及通过 SSL 方式认证的 Kafka 集群。

4.5.1 准备kafka环境

像下面这样,提前创建一个topic,确保生产端发送的消息可以被消费端收到

4.5.2 创建一张测试表

该表用于后面从kafka中接收存储数据,建表sql如下

create table user_kafka(
	id int,
	name varchar(50),
	age int
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 10
PROPERTIES("replication_num" = "1");

4.5.3 发送几条消息到kafka

在上述的kafka发送消息的窗口中,发送下面2条消息

{"id":1,"name":"jike","age":23}
{"id":2,"name":"tank","age":19}

4.5.4 创建导入作业

desired_concurrent_number指定并行度

CREATE ROUTINE LOAD doris_db.kafka_job2 on user_kafka
PROPERTIES
(
    "desired_concurrent_number"="1",
	"strict_mode"="false",
    "format" = "json"
)
FROM KAFKA
(
    "kafka_broker_list"= "kafka服务IP地址:9092",
    "kafka_topic" = "test",
    "property.group.id" = "test_group_1",
    "property.kafka_default_offsets" = "OFFSET_BEGINNING",
    "property.enable.auto.commit" = "false"
);

执行成功后,检查数据表,可以发现数据导入成功了,这个可能存在一定的延迟

补充:

  • 查看导入作业状态

    • SHOW ALL ROUTINE LOAD

  • 修改作业属性

    • 用户可以修改已经创建的作业。具体说明可以通过 HELP ALTER ROUTINE LOAD; 命令查看

  • 作业的启停控制

    • 停止作业 : STOP ROUTINE LOAD FOR 作业名称;

    • 暂停作业 : PAUSE ROUTINE LOAD FOR 作业名称;

    • 恢复作业 : RESUME ROUTINE LOAD FOR 作业名称;

五、数据删除

在日常使用中,删除数据也是经常涉及到的操作,接下来说明如何在Doris中删除数据。

5.1 删除语法

Delete不同于其他导入方式,它是一个同步过程,与Insert into相似,所有的Delete操作在Doris中是一个独立的导入作业,一般Delete语句需要指定表和分区以及删除的条件来筛选要删除的数据,并将会同时删除base表和rollup表的数据。参考文档:操作 - DELETE - 《Apache Doris v1.2 中文文档》 - 书栈网 · BookStack

完整语法

DELETE FROM table_name [PARTITION partition_name | PARTITIONS (p1, p2)]
WHERE
column_name1 op { value | value_list } [ AND column_name2 op { value | value_list } ...];

参数说明:

  1. op 的可选类型包括:=, >, <, >=, <=, !=, in, not in

  2. 使用聚合类的表模型(AGGREGATE、UNIQUE)只能指定 key 列上的条件。

  3. 当选定的 key 列不存在于某个 rollup 中时,无法进行 delete。

  4. 条件之间只能是“与”的关系。若希望达成“或”的关系,需要将条件分写在两个 DELETE 语句中。

  5. SinceVersion 1.2 如果为分区表,需要指定分区,如果不指定,doris 会从条件中推断出分区。两种情况下,doris 无法从条件中推断出分区: 1) 条件中不包含分区列;2) 分区列的 op 为 not in。当分区表未指定分区,或者无法从条件中推断分区的时候,需要设置会话变量 delete_without_partition 为 true,此时 delete 会应用到所有分区。

5.2 操作演示

删除user_kafka 中id为1的数据

delete from user_kafka_copy where id = 1;

在上述的删除中我们并没有指定分区也可以删除成功,为什么呢?因为我们的表的分区为单分区,只有单分区才可以这么使用,如果是多分区这样操作会报错。

删除指定分区的数据,需要先找到数据所在的分区名称,可以在控制台界面上定位分区名字

DELETE FROM user_kafka_copy PARTITION user_kafka_copy where id = 2;

5.2.1 删除语法补充说明

delete from 类似标准mysql的 delete 语法和使用,具体可查看 help delete 命令帮助,下面补充几点使用过程中的注意事项:

  • 语句只能针对 Partition 级别进行删除。如果一个表有多个 partition 含有需要删除的数据,则需要执行多次针对不同 Partition 的 delete 语句。而如果是没有使用 Partition 的表,partition 的名称即表名。

  • where 后面的条件谓词只能针对 Key 列,并且谓词之间,只能通过 AND 连接。如果想实现 OR 的语义,需要执行多条 delete。

  • delete 是一个同步命令,命令返回即表示执行成功。

  • 从代码实现角度,delete 是一种特殊的导入操作。该命令所导入的内容,也是一个新的数据版本,只是该版本中只包含命令中指定的删除条件。在实际执行查询时,会根据这些条件进行查询时过滤。所以,不建议大量频繁使用 delete 命令,因为这可能导致查询效率降低。

  • 数据的真正删除是在 BE 进行数据 Compaction 时进行的。所以执行完 delete 命令后,并不会立即释放磁盘空间。

  • delete 命令一个较强的限制条件是,在执行该命令时,对应的表,不能有正在进行的导入任务(包括 PENDING、ETL、LOADING)。而如果有 QUORUM_FINISHED 状态的导入任务,则可能可以执行。

  • delete 也有一个隐含的类似 QUORUM_FINISHED 的状态。即如果 delete 只在多数副本上完成了,也会返回用户成功。但是会在后台生成一个异步的 delete job(Async Delete Job),来继续完成对剩余副本的删除操作。如果此时通过 show delete 命令,可以看到这种任务在 state 一栏会显示 QUORUM_FINISHED。

六、写在文末

本文通过案例操作详细演示了Doris与表操作相关的语法,对于学习Doris的同学来说,掌握基础的语法对于后续深入学习和掌握Doris的高级语法有着重要的意义,本篇到此结束感谢观看。

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

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

相关文章

Android KMP 快速入门2 - Koin依赖注入

这里写目录标题 代码仓库KMP 框架基本框架actual&expectKoin 依赖注入管理 代码仓库 本小节代码已经上传到gitee&#xff0c;请自行查看&#xff1a; 点击访问仓库 KMP 框架 基本框架 源码集合描述存放内容示例androidMain针对 Android 平台的代码使用 Android SDK、Andr…

Python、C++、java阶乘算法

最近&#xff0c;我除了Python还学了C和Java&#xff0c;然后在网上看到编程考题&#xff1a;阶乘。 首先&#xff0c;我们先理解什么是阶乘。 阶乘是数学中的一个概念&#xff0c;通常定义为从1乘到指定的数。具体来说&#xff0c;一个正整数的阶乘&#xff08;记作n!&#…

【课程学习】Wireless Communications

Goldsmith A. Wireless communications[M]. Cambridge university press, 2005. Wireless Communications 无线通信课程 文章目录 2-Path Loss, Shadowing, and Multipath2.4-Two-Ray Multipath Model时延扩展 delay spread P33 3-Statistical Multipath Channel Models3.3-Wid…

Python+Matplotlib创建高等数学上册P2页例3交互动画

import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider from matplotlib.patches import Rectangle# 创建图形和坐标轴 fig, ax plt.subplots(figsize(12, 8)) plt.subplots_adjust(bottom0.2)# 设置坐标轴范围 ax.set_xlim(-2*np.pi, 2…

BugReport中的App Processor wakeup字段意义

一、功耗字段意义&#xff1a; App processor wakeup:Netd基于xt_idletimer 待机下监视网络设备的收发工作状态&#xff0c;即当设备发生联网从休眠态变成为唤醒态时&#xff0c;会记录打醒者的uid(uid大于0)和网络类型(wifi或数据类型)、时间戳 实际日志&#xff1a;我们在B…

【C++复习】C++11经典语法

文章目录 {}列表初始化1. 初始化内置类型变量2. 初始化数组3. 初始化标准容器4. 初始化自定义类型5. 构造函数初始化列表6. 初始化列表&#xff08;initializer_list&#xff09;7. 返回值初始化8. 静态成员变量和全局变量的就地初始化9. 防止类型收窄总结 decltype右值引用完美…

图像处理案例04

图像处理 问题&#xff1a;把不规则的图片按照参考图摆放 步骤&#xff1a; 1. 用ORB找关键点 2. 关键点匹配 3. 根据上一步匹配的关键点得出单应性矩阵 4. 根据单应性矩阵对不规则进行透视变换 import cv2 import numpy as np import matplotlib.pyplot as pltimgl cv2.imrea…

精华帖分享 | 因子构建思考1

本文来源于量化小论坛股票量化板块精华帖&#xff0c;作者为z-coffee。 以下为精华帖正文&#xff1a; 一段时间没写帖子&#xff0c;其实一直在研究策略&#xff0c;只是从不同的角度去思考而已。熟悉我的老板其实清楚&#xff0c;我的炉子水平一般&#xff0c;基本不太依托…

什么是 Web 应用中的 Facet 控件

在 Web 页面设计和开发中&#xff0c;facet 是一个十分重要的概念&#xff0c;尤其在电子商务、数据搜索和筛选功能中非常常见。Facet 通常指的是一种分类或过滤的方式&#xff0c;用于让用户能够通过多维度的条件来细化和调整数据结果&#xff0c;从而找到更符合需求的内容。F…

资源《Arduino 扩展板5-单电机驱动》说明。

资源链接&#xff1a; Arduino 扩展板5-单电机驱动 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;AD工程、原理图、PCB。 3.内容展示 4.简述 该文件为PCB工程&#xff0c;采用AD做的。 该文件打板后配合Arduino使用&#xff0c;属于Arduino的扩展板。

ECP 集成字段非必填配置

导读 INTRODUCTION 非必填设置&#xff1a;ECP主数据同步的时候&#xff0c;经常遇到一个问题&#xff0c;就是ECP报错&#xff0c;但是这个字段两边的ecp顾问与sf顾问都觉得没实际意思&#xff0c;觉得没有传输的必要性&#xff0c;这个时候我们就可以考虑非必输的字段不必输…

Linux命令--04----文件目录类命令

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 文件目录类命令pwdls 、llcdmkdirrmdirtouchcprmmv 查看文件catmorelessheadtail 打印信息echo\> 覆盖和>>追加lnhistory 文件目录类命令 pwd ls 、ll cd…

C--编译和链接见解

欢迎各位看官&#xff01;如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论 感谢各位看官的支持&#xff01;&#xff01;&#xff01; 一&#xff1a;翻译环境和运行环境 在ANSIIC的任何一种实现中&#xff0c;存在两个不同的环境1&#xff0c;…

动手学深度学习(李沐)PyTorch 第 7 章 现代卷积神经网络

7.1 深度卷积神经网络&#xff08;AlexNet&#xff09; 在计算机视觉中&#xff0c;直接将神经网络与其他机器学习方法进行比较也许不公平。这是因为&#xff0c;卷积神经网络的输入是由原始像素值或是经过简单预处理&#xff08;例如居中、缩放&#xff09;的像素值组成的。但…

【C++】——list的介绍和模拟实现

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

亚马逊云乱扣费,被不知不觉扣钱真的好气呀

之前申请了亚马逊云12个月免费&#xff0c;一直也没用&#xff0c;也没登录&#xff0c;今天突然看到银行扣费信息&#xff0c;扣了我21美元&#xff0c;已经扣了我几个月了&#xff0c;登录亚马逊后台&#xff0c;实例为0的情况下&#xff0c;每个月都能扣21美元&#xff0c;国…

【HTML+CSS】留言板plus实现全过程

创建一个具有动态留言的简约风格留言板 在本教程中&#xff0c;我们将学习如何创建一个简约风格的留言板&#xff0c;它具备动态留言显示和一些基本动画效果。这个留言板将使用HTML和CSS构建&#xff0c;最终实现一个既美观又实用的界面。 准备工作 首先&#xff0c;确保你的…

UNRAID使用rclone挂在alist网盘

UNRAID使用rclone挂在alist网盘 需求&#xff1a;考虑异地备份&#xff0c;将部分重要的资料上传至网盘&#xff0c;保证nas中的资料安全。 考虑&#xff1a;当然网盘备份存在安全性问题&#xff0c;后续也可以通过加密的方式进行上传&#xff0c;不过这是后话&#xff0c;有精…

Python常见问题解答:从基础到进阶

Python常见问题解答&#xff1a;从基础到进阶 Python 是一种简单易学、功能强大的编程语言&#xff0c;广泛应用于数据分析、Web 开发、自动化脚本、人工智能等领域。即便如此&#xff0c;Python 开发者在编写代码的过程中&#xff0c;常常会遇到各种各样的问题。本文将从基础…

java集合 -- 面试

Java集合框架体系 ArrayList底层实现是数组 LinkedList底层实现是双向链表 HashMap的底层实现使用了众多数据结构&#xff0c;包含了数组、链表、散列表、红黑树等 List ps : 数据结构 -- 数组 ArrayList源码分析 ArrayList底层的实现原理是什么? ArrayList list new…