ClickHouse高原理与实践

news2024/11/20 20:36:54

ClickHouse高原理与实践

  • 1 ClickHouse的特性
    • 1.1. OLAP
    • 1.2. 列式存储
    • 1.3. 表引擎
    • 1.4. 向量化执行
    • 1.5. 分区
    • 1.6. 副本与分片
    • 1.7 其他特性
  • 2. ClickHouse模块设计
    • 2.1 Parser分析器与Interpreter解释器
    • 2.2 Storage
    • 2.3 Column与Field
    • 2.4 DataType
    • 2.4 Block
    • 2.5 Cluster与Replication
  • 3. MergeTree表引擎
    • 3.1 数据分区
    • 3.2 分区目录生成规则
    • 3.3 存储结构
    • 3.4 一级索引
    • 3.5 压缩数据块
    • 3.6. 数据标记文件
    • 3.7 数据查询和写入过程
  • 4. 分片与副本的原理
    • 4.1 ZooKeeper在ClickHouse中的作用
    • 4.2 Distributed表
  • 5. ClickHouse实践
  • 6. 疑问和思考
  • 7. 参考文档

ClickHouse是俄罗斯公司Yandex研发的一款开源的,用于OLAP( Online Analytical Processing,联机分析,即通过多种不同的维度审视数据。OLAP具有多维度、快速响应、聚合计算、数据切片等特点)的列式存储的数据库管理系统。

ClickHouse名称的来源是Click Stream,Data WareHouse,即基于点击事件流的数据仓库。

ClickHouse设计的初衷就是以最快的速度进行GROUP BY查询和过滤,它充分利用了列式存储,数据压缩,向量化执行,数据分片等架构特性,并且在算法选择上精益求精,因此具备了极高的实时查询性能。

ClickHouse是一款关系型数据库,支持了大部分标准SQL,具备完备的DBMS功能(DDL、DML、权限控制、数据备份与恢复、分布式管理),因此使用起来较友好。


1 ClickHouse的特性

1.1. OLAP

ClickHouse是一个OLAP数据库。OLAP(Online Analytical Processing),即联机分析处理或多维分析,它指的是通过多种不同的维度审视数据,通常会涉及到复杂的聚合计算。体现在关系模型的数据库,我们查看某个维度的数据,就是通过聚合函数计算指标数据并汇总(GROUP BY)到这个维度。在数据量非常大,汇总维度非常多的情况下,就会对数据库的性能要求非常高,而ClickHouse正是为了解决这个场景的问题而诞生的。

广告投放业务的数据BI,就是一种典型的OLAP场景:从媒体拉取的展点消数据和计算的用户行为的转化数据的数据量非常庞大,用户希望在时间、媒体、代理商、平台、账户、广告组、素材等多个维度自定义地组合起来查看和分析数据。

1.2. 列式存储

ClickHouse是列式存储的数据库,数据按列组织存储到一起,它的特点是:

  • 缩小查询数据时扫描数据的范围,比如一张表有50个列,我们需要取其中5个列分析,那么列式存储只需要扫描这5个列的列数据即可,而行式存储则需要扫描所有数据,再对每行数据取出这5个列;
  • 利于数据压缩,同一列的数据,其业务含义相同,则数据重复的可能性会更高,进而数据压缩时压缩率更高;
  • 查询时数据扫描范围更小,数据传输大小也更小,所以列式存储的数据库有优秀的查询性能。
  • 相对的是写操作时,行存储数据库只需要找到该行数据对应的索引位置写入数据即可,而列式存储需要将数据的每个列写入相应的列存储文件,因此列式存储数据库写性能不佳。
    在这里插入图片描述

1.3. 表引擎

ClickHouse为适配不同业务场景,提供了几十种表引擎:

  • MergeTree(合并树)家族:最常用的引擎,它具有支持索引、数据分区、数据副本的特点;
  • 基于外部存储构建表的表引擎:HDFS、MySQL、Kafka等,其特点是直接其他存储系统读写数据,相当于对其他存储系统做了一个代理;
  • 面向内存查询的表引擎:Memory、Set、Buffer等,此类表引擎在数据表被加载时,会将数据全部加载至内存,因此其拥有良好的查询性能。Memory表引擎被作为临时表而广泛地应用于ClickHouse内部;Set表引擎则具有去重的能力,且拥有物理存储,数据不会丢失,但是Set表引擎不能被查询,只能作为IN语句的右侧条件;
  • Log家族表引擎:为小数据量(百万级以下),一次写入多次查询的场景而设计,拥有物理存储;
  • 接口类型: Merge、 Dictionary 、Distributed,它们不是存储数据的表引擎,而是用于整合其他数据表。Merge表引擎可以作为代理查询任意数据的数据表,并最终合成一个结果集返回; Dictionary表引擎是数据字典的一层代理封装,它可以取代字典函数,让用户通过数据表查询字典; Distributed表引擎是分布式表的代理,用于分发读写请求到集群中的各个节点;

1.4. 向量化执行

向量化执行是一种将数据转换为向量形式以进行计算和分析的方法。其主要思想是将数据存储在多维数组或矩阵中,并通过使用向量和矩阵操作来执行计算。这种方法可以利用底层硬件的并行性,并且通常比使用循环和条件语句的传统方法更高效。

ClickHouse使用了CPU的SIMD指令(Single Instruction Multiple Data,即用单条指令操作多条数据),实现了向量化执行。基于向量化执行和列式存储,优化了循环处理的场景,从而提升了逻辑计算的性能。

1.5. 分区

定义:MergeTree家族表引擎的表支持数据分区,把数据按分区键区分,每个分区用单独的文件存储。这里的分区是对本地数据(同一个节点)的纵向切分,并不是把分区分到不同节点;

目的:ClickHouse分区的目的是在查询时缩小扫描数据的范围,从而提升查询性能;

使用:创建MergeTree家族表的时候可以通过PARTITION BY语句指定分区键, ClickHouse按分区键生成分区目录,插入数据时属于同一个分区的数据会被合并到同一个分区目录;

其他:MergeTree家族表引擎的特性都是基于同一个分区的数据的,比如具有去重能力的ReplacingMergeTree,它只能保证同一个分区的数据是不重复的;

1.6. 副本与分片

副本:ClickHouse的Replicated家族(以Replicated为前缀)的表引擎支持数据副本,如ReplicatedMergeTree ,ClickHouse通过ZooKeeper的分布式协同的能力实现副本之间的同步,它是多主架构,可以在任意副本上执行读写操作。通过数据副本, ClickHouse降低了丢失数据的风险;

分片:ClickHouse的Distributed表引擎支持数据分片(数据水平切分,将数据分布到不同的节点)。通过数据分片的能力,降低单个节点处理的数据容量,从而提升性能;

1.7 其他特性

完备的DBMS((Database Management System)功能:支持DDL(动态创建、修改、删除库表)、DML(增删查改)、权限控制(用户粒度设置库表操作权限)、数据备份与恢复(提供数据导出导入功能)、分布式管理(集群模式,自动管理多个数据库节点)等;

关系型数据库:ClickHouse是关系型数据库,使用表、行和列来组织和管理数据。提供了数据库、表、视图、函数等传统数据库的概念,并支持大部分标准SQL;

多主架构:集群中的每个节点角色对等,该架构的优点是资源利用率较高的同时降低了单点故障的风险;缺点是节点间数据同步延迟问题和同步难度大;

2. ClickHouse模块设计

ClickHouse处理SQL时:

  • 首先由Parser分析器解析SQL,创建AST( Abstract Syntax Tree ,抽象语法树)对象。
  • 然后由Interpreter解释器解释AST对象,聚合所需的资源,执行分支判断、设置参数等业务逻辑,并根据表引擎调用相应IStorage接口。
  • IStorage根据AST查询语句的指示要求,返回IBlockStream对象。
  • 最后Interpreter通过IBlockStream对象建立查询执行管道,完成数据查询和进一步的处理等。

在这里插入图片描述

2.1 Parser分析器与Interpreter解释器

Parser分析器负责解析SQL,创建AST对象,根据SQL语句类型(Select、Insert、Update、Alter等)不同,由不同的Parser进行解析处理。 Intercepter解释器解析AST对象,创建查询的执行管道,执行分支判断、设置参数、调用IStorage接口等业务逻辑,最后返回IBlock对象,以线程的形式建立起一个查询执行管道。
在这里插入图片描述

2.2 Storage

ClickHouse底层设计没有Table对象,而是用IStorage接口,定义了DDL、read和write方法。IStorage根据AST查询语句的要求,返回指定列的原始数据,并交由Intercepter进一步对数据进行加工、计算和过滤。 IStorage接口的函数,根据表引擎的不同,由不同的子类实现。

2.3 Column与Field

ClickHouse是列式存储数据库,内存中的一列数据用一个Column对象表示。IColumn接口定义了对数据进行各种关系运算的方法(例如插入数据的insertRangeFrom和insertFrom方法、用于分页的cut、用于过滤的filter方法),这些方法根据数据类型的不同,由相应的对象实现(ColumnString、ColumnUInt8等)。 如果需要操作单列中的一行数据,则需要使用Field对象。Field对象使用了聚合的设计模式,其内部聚合了Null、UInt64、String和Array等13种数据类型及相应的处理逻辑。

2.4 DataType

DataType负责数据的序列化和反序列化,根据数据格式不同,IDataType接口定义了多种正反序列化的方法。具体实现也是根据数据类型不同,由不同的对象实现,如DataTypeString、DataTypeArray。 Datatype不负责数据的读取,而是聚合了Column和Field,由后者读取数据。

2.4 Block

Block对象负责处理ClickHouse内部的数据操作,它的本质是由Column、DataType和列名字符串构成的三元组。Block对象对Column和DataType做了进一步的抽象和封装,简化了使用过程,从而仅通过Block对象就能完成一系列的数据操作。 Block以流的形式操作数据,流操作有两个顶层接口,IBlockInputStream负责数据的读取和关系运算,IBlockOutputStream负责将数据输出到下一环节。基于不同的表引擎,和不同的操作类型,IBlockInputStream接口共有60多个实现类,IBlockOutputStream接口有20多种实现类。

2.5 Cluster与Replication

ClickHouse的集群由分片(Shard)组成,每个分片通过副本(Replica)组成,ClickHouse的1个节点(Node)只能拥有1个分片,分片只是一个物理概念,其物理承载由副本承担。 ClickHouse副本之间数据的同步依赖于ZooKeeper的分布式协同的能力,ZooKeeper为每个分片创建一个根路径,在路径下创建一系列监听节点记录表的元数据(副本名称、列字段信息、主键分区键信息等),判断标识信息和操作日志。
在这里插入图片描述

3. MergeTree表引擎

ClickHouse的众多表引擎中,合并树((MergeTree)及其家族(*MergeTree)最为强大,只有合并树系列的表引擎才支持主键索引、数据分区、数据副本和数据采样这些特性。

家族中其他的表引擎则在MergeTree的基础之上各有所长。例如ReplacingMergeTree表引擎具有删除重复数据的特性,而SummingMergeTree表引擎则会按照排序键自动聚合数据,给MergeTree加上Replicated前缀,则变为支持数据副本的表引擎。

3.1 数据分区

  • MergeTree支持数据分区,这里的分区指的是对本地数据的纵向切分,其目的是缩小查询时扫描数据的范围。
  • MergeTree通过分区键(通过声明表时的PARTITION BY表达式)指定表数据如何进行分区,如果分区键的字段类型是整型或日期类型,则各个分区的ID为分区键的值的字符串形式,如果是其他类型,则取Hash值作为分区ID。如果没有指定分区键,则默认生成all分区。
  • MergeTree的分区目录并不是在数据表被创建之后就存在的,而是在数据写入过程中被创建的。并且随着每一批数据的写入(一次INSERT语句),MergeTree都会生成一批新的分区目录。即便不同批次写入的数据属于相同分区,也会生成不同的分区目录,在之后的某个时刻(写入后的10~15分钟,也可以手动执行optimize查询语句),ClickHouse会通过后台任务再将属于相同分区的多个目录合并成一个新的目录。

3.2 分区目录生成规则

分区目录名称由分区ID,MinBlockNum,MaxBlockNum和level这4个值用下划线拼接组成。 BlockNum为表内全局自增,每次创建新目录时加1。创建新目录时,该目录的MinBlockNum和MaxBlockNum直接取当前的BlockNum值。合并目录时,MinBlockNum取同分区目录最小的MinBlockNum,MaxBlockNum取同分区目录最大的MaxBlockNum。 创建目录时level值取0,每次合并时,level加1。

在这里插入图片描述

3.3 存储结构

MergeTree表引擎中数据是有物理存储的,数据默认存储在/var/lib/clickhouse/data目录,data目录的下一级是数据库目录,数据库目录下是各个表的目录。在表目录下,数据文件以分区目录的形式被组织存放。

分区目录下,保存着表的数据文件、索引文件、标记文件等。

每个列字段都拥有一个与之对应的[column].bin数据文件和标记文件[column].mrk,前者以压缩格式存储列数据,后者保存一列数据中每一行数据,在.bin文件中的偏移量。

在这里插入图片描述

3.4 一级索引

  • 通过PRIMARY KEY声明主键或ORDER BY表达式声明排序键,MergeTree就会生成一级索引并保存至primary.idx文件内,primary.idx文件常驻内存,取用速度极快。
  • MergeTree的一级索引是稀疏索引,每一行索引标记对应的是一段数据,而设置索引的间隔则是通过index_granularity参数(创建表时通过SETTINGS表达式设置,默认值为8192)。
  • 每个索引值根据主键或排序键生成,例如排序键声明为ORDER BY(statis_date, game_id),则第1个索引值为第1行数据的statis_date与game_id的值紧密连接的字符串值,第2个索引值为第(1+index_granularity)行数据的statis_date与game_id值连接,依次类推。

在这里插入图片描述

3.5 压缩数据块

.bin文件存储了列字段的数据,它并不是紧密地将数据写入文件,而是以压缩数据块的方式排列在一起。

一个压缩数据块由头信息和压缩数据两部分组成,头信息保存了压缩算法类型、压缩后的数据字节大小和压缩前的数据字节大小。

MergeTree在写入数据时,会按照索引粒度(每index_granularity条数据为一批)创建压缩数据块,并根据一批数据压缩前的大小size,生成一定数量的压缩块,size被控制在64KB-1MB。

压缩数据块的设计,也是为了缩小查询数据时扫描数据的范围,根据索引可以确定需要查找的数据所在的压缩块,而不用扫描整个.bin文件。通过压缩也降低了存储空间并加速了数据传输效率。考虑到数据的压缩和解压也需要消耗一定的性能,所以MergeTree控制了每个压缩块的数据大小,在性能损耗和压缩率之间寻求平衡。

3.6. 数据标记文件

MergeTree使用数据标记文件(.mrk文件)保存索引区间对应的数据压缩块的偏移量信息,它与一级索引是一一对齐的,即通过索引值和数据标记文件,就可以定位到该索引值对应的数据压缩块。

一行数据标记数据使用一个元组表示,元组包含两个整型的偏移量,分别表示此段索引区间的数据在对应的.bin压缩文件中,压缩数据块的起始偏移量(第几个压缩数据块),以及该压缩块解压后,未压缩数据的起始偏移量。

在这里插入图片描述

3.7 数据查询和写入过程

写入数据时,首先是生成分区目录(后续在某一时刻,同分区的目录会合并到一起)。在分区目录内,接着按照index_granularity索引粒度(每index_granularity条数据为一批),生成一级索引文件primary.idx,为每个列字段生成.mrk数据标记文件和.bin压缩数据文件(以压缩数据块的形式写入)。

查询数据时,首先借助分区索引(Partition By)确认数据所在的分区目录(如果根据where条件无法确定目录,则扫描所有分区目录),然后根据一级索引确认索引数据段和对应的数据标记文件(如果where条件匹配不到索引,则扫描目录内索引的最大区间),最后根据数据标记文件,确认数据所在的压缩数据块。最后MergeTree会以多线程的形式同时读取多个压缩数据块。

4. 分片与副本的原理

4.1 ZooKeeper在ClickHouse中的作用

ClickHouse Replicated家族表引擎的表支持数据副本的能力,它借助了ZooKeeper的分布式协同能力,借助ZooKeeper的消息日志广播功能,实现多个副本之间的同步(数据写入修改、分区合并、元数据修改)。

在创建ReplicatedMergeTree的表时,需要指定zk_path和副本名称replica_name。ZooKeeper会以zk_path为根路径,为这张表创建一组监听节点,这些节点用于记录表的元数据(副本名称、列字段信息、主键分区键信息等)、判断标识信息(主副选举信息、判断写入成功最低实例数等)和操作日志(副本需要执行的指令等)。

ClickHouse每个副本在本地完成操作后,会推送操作日志到/log节点,并且每个副本都会监听/log节点的变化,拉取操作日志并执行,从而实现副本间的同步。
在这里插入图片描述

4.2 Distributed表

ClickHouse通过Distributed表引擎的表作为代理来管理集群内数据的路由、分发、写入、查询等工作,它自身不存储数据,而是作为数据分片的代理,将请求路由到相应的本地表。从实体层面看,一张分片表由任意非Distributed表引擎的本地表和Distributed表引擎的分布式表这两部分组成。

创建Distributed表时需要指定集群、数据库和表名称,以及分片键。分片键要求返回一个整型的值,可以取某个整型的表字段,或者是某个字段的hash,还可以用rand()函数。集群配置中会设置每个分片的权重值weight,插入数据时根据shard_value%(sum(weight))(分片键计算的值对集群总权重取余),即可确定数据落在哪个分片。

Distributed分布式表写入:两种实现方式:一是借助外部系统计算写入数据属于哪个分片,直接写入到对应的本地表,此方式拥有更好的写入性能;二是通过Distributed表引擎代理写入分片数据。在任意一个节点的分片表写入数据时,它会根据分区规则划分数据,如果是属于本分片的数据,则直接写入,如果是其他分片的数据,则连接远程节点发送数据。

Distributed表查询:在任意一个节点的分片表查询数据时,按照分片数量将查询拆分成若干个针对本地表的子查询,然后向各个分片发起查询,最后汇总返回。

在这里插入图片描述

5. ClickHouse实践

数据类型

ClickHouse除了支持数值、字符串、日期时间这些传统数据库的基础数据类型,还支持几种复合类型和特殊类型。这使得ClickHouse的数据表达能力更加丰富立体。

部分查询场景ClickHouse会做类型检查,比如字段类型是字符串/日期,WHERE语句传数值;数值类型与字符串类型做计算;这些情况都会报错。

在这里插入图片描述

SELECT

ClickHouse是列式存储数据,SQL语句设计的字段数量会直接影响到查询时扫描的数据块范围,所以SELECT语句查询的列数量要尽可能少。

别名问题:默认情况下,如果别名和列名相同,则别名不能再次出现在其他的聚合表达式中。该问题可以通过设置prefer_column_name_to_alias 参数调整,但还是建议别名不要和列名相同。

在这里插入图片描述

WHERE与PREWHERE

WHERE条件语句字段需尽量使用主键/排序键的字段,才能借助索引优化查询速度。

PREWHERE语句:只能用于MergeTree系列的表引擎,其作用与WHERE相同,使用PREWHERE时,首先只会读取PREWHERE指定的列字段数据,用于数据过滤的条件判断。待数据过滤之后再读取SELECT声明的列字段以补全其余属性。所以在一些场合下,PREWHERE相比WHERE而言,处理的数据量更少,性能更高。

GROUP BY

GROUP BY语句是ClickHouse最凸显性能的地方。使用GROUP BY语句时,非GROUP BY的列不能直接用于SELECT语句,必须使用聚合函数,否则会报错。

对于GROUP BY语句,ClickHouse还提供了WITH TOTALS语句(使用时放在整个查询语句最后)用于计算汇总数据。

在这里插入图片描述
JOIN

ClickHouse的JOIN查询没有缓存的支持,即使是连续执行相同的SQL,也都会生成一次全新的执行计划;

在执行JOIN查询时,无论使用的是哪种连接方式,右表都会被全部加载到内存中与左表进行比较,所以应该将数据量小的表放在右侧;

在多表的连接查询时,查询会转换成两两连接的形式,这种“滚雪球”式的查询很可能带来性能问题;

WITH

ClickHouse支持CTE(Common Table Expression,公共表表达式),以增强查询语句的表达,即通过WITH关键词定义一段查询子句并指定别名,后续查询语句就可以通过这个别名使用这个子句。

语法:WITH {变量}/{表达式}/{子查询} AS {alias} SELECT…

6. 疑问和思考

暂无

7. 参考文档

暂无

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

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

相关文章

C语言.自定义类型:结构体

自定义类型:结构体 1.结构体类型的声明1.1结构体回顾1.1.1结构体的声明1.1.2结构体变量的创建和初始化 1.2结构体的特殊声明1.3结构体的自引用 2.结构体内存对齐2.1对齐规则2.2为什么存在内存对齐2.3修改默认对齐数 3.结构体传参4.结构体实现位段4.1什么是位段4.2位…

【Linux系统编程】30.pthread_exit、pthread_join、pthread_cancel

目录 pthread_exit 参数retval 测试代码1 测试结果 pthread_join 参数thread 参数retvsl 返回值 测试代码2 测试结果 pthread_cancel 参数thread 返回值 测试代码3 测试结果 pthread_exit 退出当前线程。 man 3 pthread_exit 参数retval 退出值。 NULL&#xf…

我用文心4.0给你做了一个“五一旅行助手”!行程规划、实时查询、景区讲解!

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,所以创建了“AI信息Gap”这个公众号,专注于分享AI全维度知识…

使用Gradio搭建聊天UI实现质谱AI智能问答

一、调用智谱 AI API 1、获取api_key 智谱AI开放平台网址: https://open.bigmodel.cn/overview 2、安装库pip install zhipuai 3、执行一下代码,调用质谱api进行问答 from zhipuai import ZhipuAIclient ZhipuAI(api_key"xxxxx") # 填写…

Visual studio 2019 编程控制CH341A芯片的USB设备

1、硬件 买了个USB可转IIC、或SPI、或UART的设备,主芯片是CH341A 主要说明USB转SPI的应用,绿色跳线帽选择IIC&SPI,用到CS0、SCK、MOSI、MISO这4个引脚 2、软件 2.1、下载CH341A的驱动 点CH341A官网https://www.wch.cn/downloads/CH34…

OpenCV如何实现背投(58)

返回:OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV直方图比较(57) 下一篇:OpenCV如何模板匹配(59) 目标 在本教程中,您将学习: 什么是背投以及它为什么有用如何使用 OpenCV 函数 cv::calcBackP…

Mac好用又好看的终端iTerm2 + oh-my-zsh

Mac好用又好看的终端iTerm2 1. iTerm2的下载安装2. oh-my-zsh的安装2.1 官网安装方式2.2 国内镜像源安装方式 3. oh-my-zsh配置3.1 存放主题的路径3.2 存放插件的路径3.3 配置文件路径 1. iTerm2的下载安装 官网下载: iTerm2 2. oh-my-zsh的安装 oh-my-zsh是一…

设备能源数据采集新篇章

在当今这个信息化、智能化的时代,设备能源数据的采集已经成为企业高效运营、绿色发展的重要基石。而今天,我们要向大家介绍的就是一款颠覆传统、引领未来的设备能源数据采集神器——HiWoo Box网关! 一、HiWoo Box网关:一站式解决…

C++11:shared_ptr循环引用问题

一、shared_ptr的弊端 struct Listnode {int _val;std::shared_ptr<Listnode> _prev;std::shared_ptr<Listnode> _next;Listnode(int val ):_val(val),_prev(nullptr),_next(nullptr){}~Listnode(){cout << "~Listnode()" << endl;} }; in…

探索未来,开启元宇宙之旅!

一、什么是元宇宙 元宇宙&#xff0c;这个词汇逐渐进入了公众的视野&#xff0c;引发了人们无尽的想象。 首先&#xff0c;元宇宙是什么&#xff1f;元宇宙&#xff0c;顾名思义&#xff0c;是一个虚拟现实的世界&#xff0c;一个融合了数字、物理和社交空间的全息图。它不仅…

【数据结构】位图与布隆过滤器

目录 前言 位图的概念 经典面试题目 位图的模拟实现 set() reset() test() 位图整体代码 位图的应用 位图的优缺点 布隆过滤器 布隆过滤器的概念 哈希函数的个数与布隆过滤器长度的关系 布隆过滤器的模拟实现 插入 查找 删除 布隆过滤器整体代码 前言 哈希本质…

nginx缓存清理

背景 昨天打开我的gpt镜像网站&#xff0c;意外发现静态图片资源全都无法获取了 CoCo-AI 一番排查下来&#xff0c;发现是引用的cdn链接失效了 且cdn源是属于七牛云的&#xff0c;且不再维护&#xff0c;于是果断切换到cloudflare export function getEmojiUrl(unified: str…

iBarcoder for Mac:一站式条形码生成软件

在数字化时代&#xff0c;条形码的应用越来越广泛。iBarcoder for Mac作为一款专业的条形码生成软件&#xff0c;为用户提供了一站式的解决方案。无论是零售、出版还是物流等行业&#xff0c;iBarcoder都能轻松应对&#xff0c;助力用户实现高效管理。 iBarcoder for Mac v3.14…

Android4.4真机移植过程笔记(一)

1、RK源码编译 获取内核源码&#xff1a; git clone git172.28.1.172:rk3188_kernel -b xtc_ok1000 内核编译环境&#xff1a; 从172.28.1.132编译服务器的/data1/ZouZhiPing目录下拷贝toolchain.tar.gz&#xff08;交叉编译工具链&#xff09;并解压到与rk3188_kernel同级目…

计算机英文论文常见错误写作习惯2

目录 第一部分 非常长的句子 在一个句子的主要概念的前面&#xff0c;首先说明目的、地点或原因 将表示时间的短语放在句首的倾向 将最重要的主语放在句首&#xff0c;以示强调 ‘In this paper’, ‘in this study’ 第一部分 非常长的句子 由于作者经常直接从中文翻译…

通过ESXi主机和专业工具导出或导入虚拟机

关于导出虚拟机的用户场景 导出ESXi虚拟机是VMware内置功能之一&#xff0c;可用于数据迁移或作为ESXi备份解决方案。通常情况下&#xff0c;您可以将ESXi中的虚拟机导出为OVF模板&#xff0c;该模板可捕获虚拟机或虚拟设备的状态并存储在一个自包含的包中&#xff0c;其中磁盘…

使 Elasticsearch 和 Lucene 成为最佳向量数据库:速度提高 8 倍,效率提高 32 倍

作者&#xff1a;来自 Elastic Mayya Sharipova, Benjamin Trent, Jim Ferenczi Elasticsearch 和 Lucene 成绩单&#xff1a;值得注意的速度和效率投资 我们 Elastic 的使命是将 Apache Lucene 打造成最佳的向量数据库&#xff0c;并继续提升 Elasticsearch 作为搜索和 RAG&a…

启发式搜索算法4 -遗传算法实战:吊死鬼游戏

相关文章: 启发式搜索算法1 – 最佳优先搜索算法 启发式搜索算法2 – A*算法 启发式搜索算法2 – 遗传算法 有一个小游戏叫吊死鬼游戏&#xff08;hangman&#xff09;&#xff0c;在学习英语的时候&#xff0c;大家有可能在课堂上玩过。老师给定一个英文单词&#xff0c;同学们…

Python人脸识别全面教程

目录 第一部分&#xff1a;人脸识别基础 1.1 人脸检测 1.2 人脸识别算法 1.3 深度学习在人脸识别中的应用 1.4 人脸识别库 第二部分&#xff1a;人脸识别高级技术 2.1 特征提取与人脸编码 人脸编码示例 2.2 人脸识别流程 人脸识别流程示例 2.3 多人脸识别与跟踪 多…

LabVIEW航空发动机主轴承试验器数据采集与监测

LabVIEW航空发动机主轴承试验器数据采集与监测 随着航空技术的迅速发展&#xff0c;对航空发动机性能的测试与监测提出了更高的要求。传统的数据采集与监测方法已难以满足当前高精度和高可靠性的需求&#xff0c;特别是在主轴承试验方面。基于LabVIEW的航空发动机主轴承试验器…