ClickHouse 基础(一)

news2024/12/25 1:20:55

官网

以毫秒为单位查询数十亿行

ClickHouse是用于实时应用和分析的最快、资源效率最高的开源数据库。

安装ClickHouse

使用ClickHouse,你有三个选择:

  • ClickHouse云:官方ClickHouse作为一项服务,-由ClickHouse的创建者构建,维护和支持
  • 快速安装:一个易于下载的二进制测试和开发与ClickHouse
  • 生产部署:ClickHouse可以运行在任何Linux, FreeBSD,或macOS与x86-64, ARM,或PowerPC64LE CPU架构
  • Docker镜像:使用Docker Hub中的官方Docker镜像

1、什么是ClickHouse?

ClickHouse®是一个高性能,面向列的SQL数据库管理系统(DBMS),用于在线分析处理(OLAP)。它既可以作为开源软件,也可以作为云服务。

1.1 什么是OLAP?

OLAP场景需要在大型数据集之上的实时响应,用于具有以下特征的复杂分析查询:

  • 数据集可以是巨大的——数十亿或数万亿行
  • 数据组织在包含许多列的表中
  • 只选择几个列来回答任何特定的查询
  • 结果必须以毫秒或秒为单位返回

1.2 面向列与面向行数据库

在面向行的DBMS中,数据以行为单位存储,与一行相关的所有值在物理上彼此相邻存储。

在面向列的DBMS中,数据存储在列中,来自相同列的值存储在一起。

1.3 为什么面向列的数据库在OLAP场景中工作得更好

面向列的数据库更适合OLAP场景:它们在处理大多数查询时至少快100倍

1.4 为什么ClickHouse这么快?

ClickHouse使用所有可用的系统资源来充分发挥其潜力,以尽可能快地处理每个分析查询。这是由于分析功能和对实现最快的OLAP数据库所需的底层细节的关注的独特组合而成为可能的。

深入了解这个主题的有用文章包括:

  • ClickHouse Performance
  • Distinctive Features of ClickHouse
  • FAQ: Why is ClickHouse so fast?

1.5 实时处理分析查询

在面向行的DBMS中,数据是按以下顺序存储的:
在这里插入图片描述
换句话说,与一行相关的所有值在物理上都是挨个存储的。

面向行的DBMS的例子有MySQL、Postgres和MS SQL Server。

在面向列的DBMS中,数据是这样存储的:

在这里插入图片描述
这些例子只显示了数据排列的顺序。来自不同列的值被分开存储,来自同一列的数据被一起存储。

面向列DBMS的例子:Vertica, Paraccel (Actian Matrix和Amazon Redshift), Sybase IQ, Exasol, Infobright, InfiniDB, MonetDB (VectorWise和Actian Vector), LucidDB, SAP HANA, Google Dremel, Google PowerDrill, Druid和kdb+。

不同的数据存储顺序更适合不同的场景。数据访问场景指的是进行什么查询、查询的频率和比例;每种查询类型要读取多少数据——行、列和字节;读取和更新数据的关系;数据的工作大小以及如何在本地使用它;是否使用事务,以及它们的隔离程度;数据复制和逻辑完整性要求;对每种查询类型的延迟和吞吐量的需求,等等。

系统负载越高,定制系统设置以匹配使用场景的需求就越重要,定制的粒度也就越细。没有一个系统能同样适合于不同的场景。如果系统能够适应广泛的场景,那么在高负载下,系统处理所有场景的能力都很差,或者只能很好地处理一个或几个可能的场景。

OLAP场景的关键属性

  • 表是“宽”的,这意味着它们包含大量的列。
  • 数据集很大,查询在处理单个查询时需要高吞吐量(每台服务器每秒多达数十亿行)。
  • 列值相当小:数字和短字符串(例如,每个URL 60字节)。
  • 查询提取大量行,但只提取一小部分列。
  • 对于简单的查询,允许大约50毫秒的延迟。
  • 每个查询都有一个大表;所有的表都很小,除了一张。
  • 查询结果明显小于源数据。换句话说,数据被过滤或聚合,因此结果适合单个服务器的RAM。
  • 查询相对较少(通常每个服务器每秒有数百个或更少的查询)。
  • 插入以相当大的批量(> 1000行)进行,而不是以单行进行。
  • 事务是不必要的。

很容易看出,OLAP场景与其他流行的场景(如OLTP或Key-Value访问)非常不同。因此,如果您想获得良好的性能,尝试使用OLTP或Key-Value DB来处理分析查询是没有意义的。例如,如果您尝试使用MongoDB或Redis进行分析,那么与OLAP数据库相比,您将获得非常差的性能。

输入输出

1)对于分析查询,只需要读取少量的表列。在面向列的数据库中,您可以只读取所需的数据。例如,如果您需要100列中的5列,那么I/O可以减少20倍。
2)由于数据是以块(packets)的形式读取的,因此更容易压缩。列中的数据也更容易压缩。这进一步减少了I/O量。
3)由于减少了I/O,更多的数据可以放入系统缓存。

例如,查询“计数每个广告平台的记录数”需要读取一个“广告平台ID”列,该列未压缩占用1字节。如果大多数流量不是来自广告平台,你可以预期这个专栏的压缩至少是原来的10倍。当使用快速压缩算法时,可以以每秒至少几gb的未压缩数据的速度进行数据解压缩。换句话说,该查询可以在单个服务器上以大约每秒几十亿行的速度处理。这个速度实际上是在实践中达到的。

CPU

由于执行查询需要处理大量行,因此可以为整个向量(vectors )而不是单独的行分派所有操作,或者实现查询引擎,以便几乎没有分派成本。如果不这样做,对于任何不太好的磁盘子系统,查询解释器不可避免地会使CPU停滞。在列中存储数据和在可能的情况下按列处理数据是有意义的。

有两种方法:
1)矢量引擎。所有的操作都是针对向量编写的,而不是针对单独的值。这意味着您不需要经常调用操作,并且调度成本可以忽略不计。操作代码包含一个优化的内部循环。

2)代码生成。为查询生成的代码包含所有间接调用。

在面向行的数据库中不会这样做,因为在运行简单查询时,这样做没有意义。然而,也有例外。例如,MemSQL使用代码生成来减少处理SQL查询时的延迟。(相比之下,分析型DBMS需要优化吞吐量,而不是延迟。)

注意,为了提高CPU效率,查询语言必须是声明式的(SQL或MDX),或者至少是向量(J, K)。查询应该只包含隐式循环,以便进行优化。

2、Quick Start

2.1 下载二进制文件

ClickHouse本机运行在Linux、FreeBSD和macOS上,并通过WSL运行在Windows上。在本地下载ClickHouse的最简单方法是运行以下curl命令。它决定你的操作系统是否被支持,然后下载一个合适的ClickHouse二进制文件:

curl https://clickhouse.com/ | sh

# 安装
 ./clickhouse install
 
 Start clickhouse-server with:
 sudo clickhouse start

Start clickhouse-client with:
 clickhouse-client --password

2.2 启动服务器

运行如下命令启动ClickHouse服务:

./clickhouse server

2.3 启动客户端

使用ClickHouse -client连接到ClickHouse服务。打开一个新的终端,更改clickhouse二进制文件的保存目录,并运行以下命令:

./clickhouse client

当它连接到本地主机上运行的服务时,你应该看到一个笑脸:

my-host :)

2.4 创建表

使用CREATE TABLE定义一个新表。典型的SQL DDL命令与一个添加可以工作在ClickHouse-表在ClickHouse需要一个ENGINE子句。使用MergeTree来利用ClickHouse的性能优势:

CREATE TABLE my_first_table
(
    user_id UInt32,
    message String,
    timestamp DateTime,
    metric Float32
)
ENGINE = MergeTree
PRIMARY KEY (user_id, timestamp)

2.5 插入数据

您可以在ClickHouse中使用熟悉的INSERT INTO TABLE命令,但重要的是要了解,每次插入到MergeTree表中都会导致在存储中创建一个part (文件夹)。为了最小化parts,一次批量插入许多行(一次插入数万甚至数百万行)。

INSERT INTO my_first_table (user_id, message, timestamp, metric) VALUES
    (101, 'Hello, ClickHouse!',                                 now(),       -1.0    ),
    (102, 'Insert a lot of rows per batch',                     yesterday(), 1.41421 ),
    (102, 'Sort your data based on your commonly-used queries', today(),     2.718   ),
    (101, 'Granules are the smallest chunks of data read',      now() + 5,   3.14159 )

2.6 查询新表

你可以写一个SELECT查询,就像你会用任何SQL数据库:

 SELECT *
 FROM my_first_table
 ORDER BY timestamp

注意,响应以一个漂亮的表格格式返回:
在这里插入图片描述

2.7 插入自己的数据

下一步是将你当前的数据输入ClickHouse。我们有很多表函数和集成来获取数据。我们在下面的选项卡中有一些例子,或者查看我们的集成列表,了解与ClickHouse集成的一长串技术。
在这里插入图片描述

下一步?

  • 查看高级教程,深入了解ClickHouse的关键概念和功能
  • 通过参加ClickHouse Academy的免费点播培训课程继续学习
  • 我们有一个示例数据集的列表,并说明如何插入它们
  • 如果您的数据来自外部源,请查看我们的集成指南集,了解如何连接到消息队列、数据库、管道等
  • 如果您使用的是UI/BI可视化工具,请查看连接UI到ClickHouse的-用户指南
  • 关于主键的用户指南是您需要了解的关于主键以及如何定义它们的所有内容

3、高级教程

在本教程中,您将创建一个表并插入一个大型数据集(200万行纽约出租车数据)。然后,您将在数据集上运行查询,包括如何创建字典并使用它执行JOIN的示例。

3.1 创建一个新表

纽约市的出租车数据包含数百万次出租车出行的详细信息,包括接送时间和地点、成本、小费金额、通行费、付款类型等列。让我们创建一个表来存储这些数据…

连接到SQL控制台

default数据库中创建如下trips表:

CREATE TABLE trips
(
    `trip_id` UInt32,
    `vendor_id` Enum8('1' = 1, '2' = 2, '3' = 3, '4' = 4, 'CMT' = 5, 'VTS' = 6, 'DDS' = 7, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14, '' = 15),
    `pickup_date` Date,
    `pickup_datetime` DateTime,
    `dropoff_date` Date,
    `dropoff_datetime` DateTime,
    `store_and_fwd_flag` UInt8,
    `rate_code_id` UInt8,
    `pickup_longitude` Float64,
    `pickup_latitude` Float64,
    `dropoff_longitude` Float64,
    `dropoff_latitude` Float64,
    `passenger_count` UInt8,
    `trip_distance` Float64,
    `fare_amount` Float32,
    `extra` Float32,
    `mta_tax` Float32,
    `tip_amount` Float32,
    `tolls_amount` Float32,
    `ehail_fee` Float32,
    `improvement_surcharge` Float32,
    `total_amount` Float32,
    `payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
    `trip_type` UInt8,
    `pickup` FixedString(25),
    `dropoff` FixedString(25),
    `cab_type` Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
    `pickup_nyct2010_gid` Int8,
    `pickup_ctlabel` Float32,
    `pickup_borocode` Int8,
    `pickup_ct2010` String,
    `pickup_boroct2010` String,
    `pickup_cdeligibil` String,
    `pickup_ntacode` FixedString(4),
    `pickup_ntaname` String,
    `pickup_puma` UInt16,
    `dropoff_nyct2010_gid` UInt8,
    `dropoff_ctlabel` Float32,
    `dropoff_borocode` UInt8,
    `dropoff_ct2010` String,
    `dropoff_boroct2010` String,
    `dropoff_cdeligibil` String,
    `dropoff_ntacode` FixedString(4),
    `dropoff_ntaname` String,
    `dropoff_puma` UInt16
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(pickup_date)
ORDER BY pickup_datetime;

3.2 插入数据集

现在已经创建了一个表,让我们添加NYC出租车数据。它在S3中的CSV文件中,您可以从那里加载数据。

1)下面的命令将来自S3中两个不同文件的~2,000,000行插入到trips表中:
trips_1.tsv.gz and trips_2.tsv.gz

INSERT INTO trips
SELECT * FROM s3(
    'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{1..2}.gz',
    'TabSeparatedWithNames', "
    `trip_id` UInt32,
    `vendor_id` Enum8('1' = 1, '2' = 2, '3' = 3, '4' = 4, 'CMT' = 5, 'VTS' = 6, 'DDS' = 7, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14, '' = 15),
    `pickup_date` Date,
    `pickup_datetime` DateTime,
    `dropoff_date` Date,
    `dropoff_datetime` DateTime,
    `store_and_fwd_flag` UInt8,
    `rate_code_id` UInt8,
    `pickup_longitude` Float64,
    `pickup_latitude` Float64,
    `dropoff_longitude` Float64,
    `dropoff_latitude` Float64,
    `passenger_count` UInt8,
    `trip_distance` Float64,
    `fare_amount` Float32,
    `extra` Float32,
    `mta_tax` Float32,
    `tip_amount` Float32,
    `tolls_amount` Float32,
    `ehail_fee` Float32,
    `improvement_surcharge` Float32,
    `total_amount` Float32,
    `payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
    `trip_type` UInt8,
    `pickup` FixedString(25),
    `dropoff` FixedString(25),
    `cab_type` Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
    `pickup_nyct2010_gid` Int8,
    `pickup_ctlabel` Float32,
    `pickup_borocode` Int8,
    `pickup_ct2010` String,
    `pickup_boroct2010` String,
    `pickup_cdeligibil` String,
    `pickup_ntacode` FixedString(4),
    `pickup_ntaname` String,
    `pickup_puma` UInt16,
    `dropoff_nyct2010_gid` UInt8,
    `dropoff_ctlabel` Float32,
    `dropoff_borocode` UInt8,
    `dropoff_ct2010` String,
    `dropoff_boroct2010` String,
    `dropoff_cdeligibil` String,
    `dropoff_ntacode` FixedString(4),
    `dropoff_ntaname` String,
    `dropoff_puma` UInt16
") SETTINGS input_format_try_infer_datetimes = 0

2)等待INSERT操作完成——下载150mb的数据可能需要一些时间。

s3函数很聪明地知道如何解压缩数据,TabSeparatedWithNames格式告诉ClickHouse数据是用制表符分隔的,并跳过每个文件的标题行。

3)当插入完成后,验证它是否工作:

SELECT count() FROM trips

您应该看到大约2M行(准确地说是1,999,657行)。
在这里插入图片描述
注意ClickHouse需要处理的行数和速度有多快?只需处理6行,就可以在0.001秒内得到计数。(6恰好是trips表当前拥有的parts 数,部件知道它们有多少行。)

4)如果你运行一个需要访问每一行的查询,你会注意到需要处理更多的行,但运行时间仍然非常快:

SELECT DISTINCT(pickup_ntaname) FROM trips

在这里插入图片描述

该查询必须处理2M行并返回190个值,但请注意,它在大约1秒内完成了此操作。pickup_ntaname列表示出租车在纽约市的开始地。

3.3 分析数据

让我们运行一些查询来分析这2M行数据…

1)我们将从一些简单的计算开始,比如计算平均小费金额:

SELECT round(avg(tip_amount), 2) FROM trips

在这里插入图片描述
2)下面的查询基于乘客数量计算平均成本:

SELECT
    passenger_count,
    ceil(avg(total_amount),2) AS average_total_amount
FROM trips
GROUP BY passenger_count

在这里插入图片描述

3)下面是一个查询,计算每个社区每天的接送次数:

SELECT
    pickup_date,
    pickup_ntaname,
    SUM(1) AS number_of_trips
FROM trips
GROUP BY pickup_date, pickup_ntaname
ORDER BY pickup_date ASC

在这里插入图片描述
4)该查询计算行程长度,并根据该值对结果进行分组:

SELECT
    avg(tip_amount) AS avg_tip,
    avg(fare_amount) AS avg_fare,
    avg(passenger_count) AS avg_passenger,
    count() AS count,
    truncate(date_diff('second', pickup_datetime, dropoff_datetime)/60) as trip_minutes
FROM trips
WHERE trip_minutes > 0
GROUP BY trip_minutes
ORDER BY trip_minutes DESC

在这里插入图片描述
5)这个查询显示了每个社区的接送次数,按小时分列:

SELECT
    pickup_ntaname,
    toHour(pickup_datetime) as pickup_hour,
    SUM(1) AS pickups
FROM trips
WHERE pickup_ntaname != ''
GROUP BY pickup_ntaname, pickup_hour
ORDER BY pickup_ntaname, pickup_hour

在这里插入图片描述

3.4 创建字典

如果你是ClickHouse的新手,了解字典(dictionaries)的工作原理是很重要的。考虑字典的一种简单方法是存储在内存中的键->值对的映射。详细信息和字典的所有选项链接在本教程的末尾。

1)让我们看看如何在ClickHouse服务中创建与表关联的字典。表和字典将基于包含265行的CSV文件,其中一行代表纽约市的每个社区。这些社区被映射到纽约市的行政区名称(纽约市有5个行政区:布朗克斯、布鲁克林、曼哈顿、皇后区和斯塔顿岛),这个文件也将纽瓦克机场(EWR)列为一个行政区。

这是CSV文件的一部分(为清晰起见显示为表格)。文件中的LocationID列映射到trips表中的pickup_nyct2010_giddropff_nyct2010_gid列:
在这里插入图片描述
2)该文件的URL为https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/taxi_zone_lookup.csv。运行以下SQL语句,创建一个名为taxi_zone_dictionary的字典,并从S3中的CSV文件填充字典:

CREATE DICTIONARY taxi_zone_dictionary
(
  `LocationID` UInt16 DEFAULT 0,
  `Borough` String,
  `Zone` String,
  `service_zone` String
)
PRIMARY KEY LocationID
SOURCE(HTTP(URL 'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/taxi_zone_lookup.csv' FORMAT 'CSVWithNames'))
LIFETIME(MIN 0 MAX 0)
LAYOUT(HASHED_ARRAY())

LIFETIME设置为0意味着此字典将永远不会更新其源。这里使用它来避免向S3存储桶发送不必要的流量,但通常您可以指定任何您喜欢的生命周期值。
例如:
LIFETIME(MIN 1 MAX 10)
指定要在1到10秒之间的随机时间之后更新的字典。(当在大量服务器上更新时,为了在字典源上分配负载,随机时间是必要的。)

3)验证它的工作-你应该得到265行(每个邻居一行):

SELECT * FROM taxi_zone_dictionary

在这里插入图片描述
4)使用dictGet 函数(或其变体)从字典中检索值。传入字典的名称、所需的值和键(在我们的示例中是taxxi_zone_dictionaryLocationID列)。

例如,下面的查询返回LocationID为132的Borough(如上所示为JFK机场):

SELECT dictGet('taxi_zone_dictionary', 'Borough', 132)

在这里插入图片描述
5)使用dictHas函数查看字典中是否存在键。例如,下面的查询返回1(在ClickHouse中为“true”):

SELECT dictHas('taxi_zone_dictionary', 132)

在这里插入图片描述
6)下面的查询返回0,因为4567不是字典中LocationID的值:

SELECT dictHas('taxi_zone_dictionary', 4567)

在这里插入图片描述
7)使用dictGet 函数在查询中检索市镇的名称。例如:

SELECT
    count(1) AS total,
    dictGetOrDefault('taxi_zone_dictionary','Borough', toUInt64(pickup_nyct2010_gid), 'Unknown') AS borough_name
FROM trips
WHERE dropoff_nyct2010_gid = 132 OR dropoff_nyct2010_gid = 138
GROUP BY borough_name
ORDER BY total DESC

这个查询汇总了每个行政区在拉瓜迪亚机场或肯尼迪机场结束的出租车次数。结果如下所示,请注意,有相当多的行程的落点是未知的:

在这里插入图片描述

3.5 执行 Join

让我们编写一些查询,将tax_zone_dictionarytrips表连接起来。

1)我们可以从一个简单的JOIN开始,它的作用类似于上面的机场查询:

SELECT
    count(1) AS total,
    Borough
FROM trips
JOIN taxi_zone_dictionary ON toUInt64(trips.pickup_nyct2010_gid) = taxi_zone_dictionary.LocationID
WHERE dropoff_nyct2010_gid = 132 OR dropoff_nyct2010_gid = 138
GROUP BY Borough
ORDER BY total DESC

在这里插入图片描述

注意,上面JOIN查询的输出与之前使用dictGetOrDefault的查询相同(只是不包括Unknown值)。在幕后,ClickHouse实际上调用了taxxi_zone_dictionary字典的dictGet函数,但是SQL开发人员更熟悉JOIN语法。

2)我们不经常在ClickHouse中使用SELECT * -你应该只检索你实际需要的列!但是很难找到一个花费很长时间的查询,所以这个查询故意选择每一列并返回每一行(除了在默认情况下响应中有一个内置的10,000行最大值),并且还使用字典对每一行进行右连接:

SELECT *
FROM trips
JOIN taxi_zone_dictionary
    ON trips.dropoff_nyct2010_gid = taxi_zone_dictionary.LocationID
WHERE tip_amount > 0
ORDER BY tip_amount DESC
LIMIT 1000

恭喜!
做得好——你完成了教程,希望你对如何使用ClickHouse有了更好的理解。下面是接下来该怎么做的一些选择:

  • 阅读ClickHouse的主键是如何工作的——这些知识将使你在成为ClickHouse专家的过程中有很长的路要走
  • 集成外部数据源,如文件、Kafka、PostgreSQL、数据管道或许多其他数据源
  • 连接您最喜欢的UI/BI工具到ClickHouse
  • 查看SQL参考并浏览各种函数。ClickHouse有一个惊人的功能集合,用于转换,处理和分析数据
  • 了解更多字典

Glossary

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

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

相关文章

C语言中关于#include的一些小知识

写代码的过程中,因为手误,重复包含了头文件 可以看到没有报错 如果是你自己编写的头文件,那么如果没加唯一包含标识的话,那么编译器会编译报错的。如果是系统自带的头文件,由于其每个头文件都加了特殊标识&#xff0c…

【软考】系统集成项目管理工程师(十六)变更管理【1分】

一、 变更的概念 1、定义、原因、分类 2、变更流程 二、 变更的原则 1、变更管理原则、配置管理工具 2、变更管理流程 三、 变更的流程及角色职责 1、提出变更申请、变更影响分析 2、变更测试 1、有些变更很小,客户着急要,可以不用走变更程序直接修改…

Android widget基础指南

widget的概念最早是由一名叫Rose的苹果工程师提出,后来经过多方面机缘巧合的发展下,便有了今天Android平台上的小组件widget,一般APP开发可能应用场景较少,最常见的莫过于天气APP的widget。但对于从事IOT或车载方向的同学&#xf…

FL Studio2024年最新21.2破解中文版本下载地址

FL Studio 21的中文版本是一款非常受欢迎的音乐制作软件,它为用户提供了丰富的功能和工具,使他们能够轻松创作和编辑音乐。以下是一些关于FL Studio 21中文版本的主要特点和功能: FL Studio 21 Win-安装包下载如下: https://wm.makeding.co…

- 工程实践 - 《QPS百万级的有状态服务实践》03 - 消息队列

本文属于专栏《构建工业级QPS百万级服务》 继续上篇《QPS百万级的有状态服务实践》02 - 冷启动和热更新。我们的架构如图1。上一章在热更新部分,我们引入了消息队列。本章我们介绍下各个消息队列的优缺点,并选择其中一个说下核心概念和原理。 图1 目前市…

【Go语言】Go语言的数据类型

GO 语言的数据类型 Go 语言内置对以下这些基本数据类型的支持: 布尔类型:bool 整型:int8、byte、int16、int、uint、uintptr 等 浮点类型:float32、float64 复数类型:complex64、complex128 字符串:st…

嵌入式学习 Day21

一. 文件IO: 1. lseek off_t lseek(int fd, off_t offset, int whence); 功能: 重新设定文件描述符的偏移量 参数: fd:文件描述符 offset:偏移量 whence: SEEK_SET 文件开头 …

基于STM32F407的coreJSON使用教程

目录 概述 工程建立 代码集成 函数介绍 使用示例 概述 coreJSON是FreeRTOS中的一个组件库,支持key查找的解析器,他只是一个解析器,不能生成json数据。同时严格执行 ECMA-404 JSON 标准。该库用 C 语言编写,设计符合 ISO C90…

杨氏矩阵和杨辉三角

杨氏矩阵 有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。 要求:时间复杂度小于O(N); 分析 若要满足要求时间复杂度小于O(N),就不能每一行一个个…

机器学习基础(一)理解机器学习的本质

导读:在本文中,将深入探索机器学习的根本原理,包括基本概念、分类及如何通过构建预测模型来应用这些理论。 目录 机器学习 机器学习概念 相关概念 机器学习根本:模型 数据的语言:特征与标签 训练与测试&#xf…

elementui 中 el-date-picker 控制选择当前年之前或者之后的年份

文章目录 需求分析 需求 对 el-date-picker控件做出判断控制 分析 给 el-date-picker 组件添加 picker-options 属性&#xff0c;并绑定对应数据 pickerOptions html <el-form-item label"雨量年份&#xff1a;" prop"date"><el-date-picker …

正整数A+B(PTA团体天题练习题)细节题刨析

哎呀&#xff0c;又是看似简单的AB模型&#xff0c;这题确实也是AB&#xff0c;不过这个题让我debug1个多小时才找出来问题所在&#xff0c;服了&#xff0c;真是所谓细节决定成败&#xff0c;这题也挺值得记录下来的&#xff0c;话不多嗦&#xff0c;看题 题的目标很简单&…

[ansible] playbook运用

一、复习playbook剧本 --- - name: first play for install nginx #设置play的名称gather_facts: false #设置不收集facts信息hosts: webservers:dbservers #指定执行此play的远程主机组remote_user: root #指定执行此play的用…

css3的var()函数

css3的var()函数 变量要以两个连字符--(横杆)(减号)为开头 变量可以在:root{}中定义, :root可以在css中创建全局样式变量。通过 :root本身写的样式&#xff0c;相当于 html&#xff0c;但优先级比后者高。 在CSS3中&#xff0c;var()函数是一个用于插入CSS自定义属性&#xff…

如何创建WordPress付款表单(简单方法)

您是否正在寻找一种简单的方法来创建付款功能WordPress表单&#xff1f; 小企业主通常需要创建一种简单的方法来在其网站上接受付款&#xff0c;而无需设置复杂的购物车。简单的付款表格使您可以轻松接受自定义付款金额、设置定期付款并收集自定义详细信息。 在本文中&#x…

QT编写工具基本流程(自用)

以后有人让你写工具的时候&#xff0c;可以方便用这个模版及时提高工作效率&#xff0c;可以争取早点下班。包含库目录&#xff0c;头文件目录&#xff0c;输出目录以及翻译和部署&#xff0c;基本上都全了&#xff0c;也可以做收藏用用。 文章目录 1、创建项目Dialog Widget都…

Vue | (三)使用Vue脚手架(上) | 尚硅谷Vue2.0+Vue3.0全套教程

文章目录 &#x1f4da;初始化脚手架&#x1f407;创建初体验&#x1f407;分析脚手架结构&#x1f407;关于render&#x1f407;查看默认配置 &#x1f4da;ref与props&#x1f407;ref属性&#x1f407;props配置项 &#x1f4da;混入&#x1f4da;插件&#x1f4da;scoped样…

element-plus日期选择器2次封装

预期效果 官网默认样式&#xff1a; 修改后的样式&#xff1a; 代码实现 DatePicker.vue <template><div class"date-picker-container"><el-date-picker v-model"date" change"handleChange" type"date" value-for…

TypeScript中的Omit、Pick、Partial、Required类型

首先有这么个人员接口 interface IInfo {name: string; // 姓名age: number; // 年龄height: string; // 身高phone: string; // 联系电话email: string; // 邮箱 } 1. Omit Omit类型可以从一个对象类型中 忽略某些属性 假设我们使用IInfo接口&#xff0c;但是不想要其中p…

OpenAI文生视频物理世界模型——Sora降世,AI视频领域降维打击令五大行业一夜变天!

年初六&#xff0c;OpenAI发布了“文生视频”的工具&#xff0c;Sora。AI技术变革又一次震撼了整个世界。或许你又开始担心&#xff0c;AI发展那么快&#xff0c;将会取代自己。但请记住&#xff0c;危机时代也是变革时代&#xff0c;变革就是机会。开工第一天&#xff0c;相信…