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

ClickHouse 指南(三)最佳实践 -- 跳数索引

Data Skipping Indexes

Data Skipping Indexes 2

1、简介

影响ClickHouse查询性能的因素很多。在大多数情况下,关键因素ClickHouse在计算查询WHERE子句条件时是否可以使用主键。因此,选择适用于最常见查询模式的主键对于有效的表设计至关重要。

然而,无论如何仔细地调整主键,都会不可避免地有查询用例来无法有效地使用它。用户通常依赖ClickHouse来获取时间序列类型的数据,但他们通常希望根据其他业务维度分析相同的数据,如客户id、网站URL或产品编号。在这种情况下,查询性能可能会更糟糕,因为需要对每个列值进行完整的扫描,才能应用WHERE子句条件。虽然ClickHouse在这些情况下仍然相对较快,但评估数百万或数十亿的单独的数值会导致“非索引”的查询,比基于主键的查询要慢得多。

在传统的关系数据库中,有一种方法是将一个或多个“辅助”索引附加到一个表中。这是一个b树结构,允许数据库在O(log(n))时间中找到所有匹配的行(log(n))时间,而不是O(n)时间(一个表扫描),其中n是行数。然而,这种类型的辅助索引不会用于ClickHouse(或其面向列的数据库),因为磁盘上没有单独的行来添加索引。

相反,ClickHouse提供了一种不同类型的索引,在特定情况下可以显著提高查询速度。这些结构被标记为“跳过”索引,因为它们使ClickHouse能够跳过读取保证没有匹配值的相当数量的数据块。

2、基本操作

用户只能在MergeTree表族上使用跳数索引。每个数据跳转有四个主要参数:

  • 索引名称。索引名用于在每个分区中创建索引文件。此外,在删除或具体化(materializing)索引时需要将其作为参数。
  • 索引表达式。索引表达式用于计算存储在索引中的值集。它可以是列、简单运算符及(或)由索引类型决定的函数子集的组合
  • TYPE。索引的类型控制着确定是否可以跳过读取和求值每个索引块的计算。
  • 粒度(GRANULARITY)。每个索引块由粒度颗粒组成。例如,如果主表索引的粒度为8192行,索引粒度为4,则每个索引的“块”将是32768行。

当用户创建数据跳过索引时,每个数据部分目录中将有两个额外的文件用于表。

  • skp_idx_{index_name}.idx 包含有序的表达式值
  • skp_idx_{index_name}.mrk2 包含到关联数据列文件的相应偏移量。

如果WHERE子句过滤条件的某些部分在执行查询和读取相关列文件时匹配跳数索引表达式,ClickHouse将使用索引文件数据来确定是否必须处理或可以绕过每个相关的数据块(假设该块尚未通过应用主键排除)。要使用一个非常简化的示例,请考虑下面这个加载了可预测数据的表。

CREATE TABLE skip_table
(my_key UInt64,my_value UInt64
)
ENGINE MergeTree primary key my_key
SETTINGS index_granularity=8192;INSERT INTO skip_table SELECT number, intDiv(number,4096) FROM numbers(100000000);

在执行一个不使用主键的简单查询时,扫描my_value列中的所有1亿条目:

SELECT * FROM skip_table WHERE my_value IN (125, 700);

在这里插入图片描述
现在添加一个非常基本的跳数索引:

ALTER TABLE skip_table ADD INDEX vix my_value TYPE set(100) GRANULARITY 2;

在这里插入图片描述

通常跳数索引只应用于新插入的数据,所以仅仅添加索引不会影响上面的查询。

要索引已经存在的数据,使用这个语句:

ALTER TABLE skip_table MATERIALIZE INDEX vix;

在这里插入图片描述
使用新创建的索引重新运行查询:

SELECT * FROM skip_table WHERE my_value = 125

在这里插入图片描述

ClickHouse并没有处理1亿行800兆字节的数据,而是只读取和分析了16380行262KB的数据——2个8192行的粒度。

在一个更直观的形式中,这是如何读取和选择my_value为125的4096行,以及如何跳过以下行而不从磁盘读取:

在这里插入图片描述
用户可以通过在执行查询时启用跟踪来访问有关跳过索引使用情况的详细信息。从clickhouse-client,设置send_logs_level:

SET send_logs_level='trace';

这将在尝试调优查询SQL和表索引时提供有用的调试信息。从上面的例子中,调试日志显示跳跃索引删除了除两个颗粒外的所有颗粒:

 <Debug> executeQuery: (from [::ffff:127.0.0.1]:59550) SELECT * FROM skip_table WHERE my_value = 125 (stage: Complete)<Trace> InterpreterSelectQuery: The min valid primary key position for moving to the tail of PREWHERE is -1<Debug> InterpreterSelectQuery: MergeTreeWhereOptimizer: condition "my_value = 125" moved to PREWHERE<Trace> ContextAccess (default): Access granted: SELECT(my_key, my_value) ON default.skip_table<Trace> InterpreterSelectQuery: FetchColumns -> Complete<Debug> default.skip_table (39a7ab58-a89e-4780-8b49-316b55bb16fd) (SelectExecutor): Key condition: unknown<Debug> default.skip_table (39a7ab58-a89e-4780-8b49-316b55bb16fd) (SelectExecutor): Index `vix` has dropped 12207/12209 granules.<Debug> default.skip_table (39a7ab58-a89e-4780-8b49-316b55bb16fd) (SelectExecutor): Selected 6/6 parts by partition key, 1 parts by primary key, 12209/12209 marks by primary key, 2 marks to read from 1 ranges<Trace> default.skip_table (39a7ab58-a89e-4780-8b49-316b55bb16fd) (SelectExecutor): Spreading mark ranges among streams (default reading)<Trace> default.skip_table (39a7ab58-a89e-4780-8b49-316b55bb16fd) (SelectExecutor): Reading 1 ranges in order from part all_1_36_2_103, approx. 16384 rows starting from 507904<Trace> MergeTreeSelectProcessor: PREWHERE condition was split into 1 steps: "equals(my_value, 125)"<Debug> executeQuery: Read 16384 rows, 256.00 KiB in 0.661823 sec., 24755.863727915166 rows/sec., 386.81 KiB/sec.<Debug> TCPHandler: Processed in 0.662557299 sec.

3、跳数索引类型

3.1 MinMax

minmax

这个轻量级索引类型不需要参数。它存储每个块的索引表达式的最小值和最大值(如果表达式是一个元组,它分别存储元组元素的每个成员的值)。这种类型是理想的列,通常由值松散地排序。在查询处理过程中,该索引类型通常是最不昂贵的。

这种类型的索引只适用于标量或元组表达式——索引永远不会应用于返回数组或映射数据类型的表达式。

3.2 set

set(max_rows)

这种轻量级索引类型接受每个块值集的max_size的单个参数(0允许无限数量的离散值)该集合包含块中的所有值(如果值的数量超过max_size则为空;max_rows=0表示“没有限制”)。这种索引类型适用于每组粒度(本质上是“聚集在一起”)中基数较低但总体基数较高的列。

此索引的成本、性能和有效性取决于块内的基数。如果每个块包含大量唯一值,那么针对大型索引集评估查询条件的代价将非常昂贵,或者由于索引超过max_size而为空,因此索引将不被应用。

3.3 Bloom Filter Types(布隆过滤器类型)

布隆过滤器是一种数据结构,它允许以很小的误报概率为代价对集合成员进行空间效率测试。在跳数索引的情况下,误报不是一个重要的问题,因为唯一的缺点是读取一些不必要的块。但是误报的可能性确实意味着索引表达式应该为真,否则可能会跳过有效数据。

因为Bloom过滤器可以更有效地处理对大量离散值的测试,所以它们可以适用于产生更多要测试的值的条件表达式。特别是,Bloom过滤器索引可以应用于数组(其中测试数组的每个值)和映射(map,通过使用mapKeys或mapValues函数将键或值转换为数组)。

有三种基于Bloom过滤器的跳数索引类型:

  • 基本的bloom_filter,它接受一个可选参数,即允许的“误报”率在0到1之间(如果未指定,则使用0.025)。
    语法: bloom_filter([false_positive])

  • 专用的tokenbf_v1。它有三个参数,都与调整所使用的布隆过滤器有关:

    • 1)过滤器的大小(以字节为单位)(更大的过滤器的误报更少,但需要一定的存储成本);
    • 2)应用哈希函数的数量(同样,更多的哈希过滤器可以减少误报);
    • 3)布隆过滤器哈希函数的种子。
      有关这些参数如何影响布隆过滤器功能的更多细节,请参阅这里的计算器。这类索引只使用字符串、FixedString和Map datatypes。输入表达式被分割成由非字母数字字符分隔的字符序列。例如,This is a candidate for a "full text" search列值将包含This is a candidate for full text search它旨在用于LIKEEQUALSinhasToken()和类似的搜索,在较长的字符串中查找单词和其他值。例如,一种可能的用途是在自由格式的应用程序日志行列中搜索少量的类名或行号。

    语法:tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed)

  • 专门的ngrambf_v1(多元组布隆过滤器)。该索引的功能与令牌索引相同。在布隆过滤器设置之前,它需要一个额外的参数,即要索引的元组的大小。ngram是任何字符长度为n的字符串,因此ngram大小为4的字符串A short string 将被索引为:

'A sh', ' sho', 'shor', 'hort', 'ort ', 'rt s', 't st', ' str', 'stri', 'trin', 'ring'

这个索引对于文本搜索也很有用,特别是没有单词分隔的语言,比如中文。
语法:ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed)

4、跳数索引函数

跳数索引的核心目的是限制热门查询分析的数据量。考虑到ClickHouse数据的分析性质,这些查询的模式在大多数情况下包括函数表达式。因此,跳数索引必须与常用函数正确交互才能提高效率。这可能发生在以下情况:

  • 插入数据,将索引定义为函数表达式(由索引文件中存储的表达式的结果),或
  • 处理查询并将表达式应用于存储的索引值,以确定是否排除该块。

每种类型的跳数索引都适用于适合这里列出的索引实现的可用ClickHouse函数的子集。通常,集合索引和基于Bloom过滤器的索引(另一种类型的集合索引)都是无序的,因此不适用于范围。相比之下,minmax 索引特别适合于范围,因为确定范围是否相交非常快。部分匹配函数LIKE、startsWith、endsWith和hasToken的有效性取决于所使用的索引类型、索引表达式和数据的特定形态。

5、跳数索引设置

有两种设置适用于跳数索引。

  • use_skip_indexes (0 or 1, default 1) 并非所有查询都能有效地使用跳数索引。如果特定的过滤条件可能包括大多数数度,则应用数据跳过索引会产生不必要的,有时甚至是巨大的成本。对于不太可能从跳数索引中获益的查询,将该值设置为0
  • force_data_skipping_indices (以逗号分隔的索引名称列表)。此设置可用于防止某些类型的低效查询。在某些情况下,除非使用跳跃索引,否则查询表的开销太大,对一个或多个索引名使用此设置将为不使用列出的索引的任何查询返回异常。这将防止编写糟糕的查询消耗服务器资源。

6、跳数最佳实践

跳数索引并不直观,特别是对于习惯于使用RDMS领域中基于行的辅助索引或文档存储中反向索引的用户。为了获得任何好处,应用ClickHouse跳数索引必须避免足够的粒度的读取,以抵消计算索引的成本。关键的是,如果一个值在索引块中出现一次,这意味着必须将整个块读入内存并求值,索引成本是不必要的。

考虑以下数据分布:
在这里插入图片描述

假设主键/order by键是timestamp,并且在visitor_id上有一个索引。考虑下面的查询:

SELECT timestamp, url FROM table WHERE visitor_id = 1001

对于这种数据分布,传统的辅助索引是非常有利的。辅助索引将只包含5个行位置,而不是读取所有32768行来查找具有所请求的visitor_id的5行,并且只从磁盘读取这5行。对于ClickHouse 跳数索引,情况正好相反。无论跳过 跳数的类型如何,都将测试visitor_id列中的所有32768个值。

因此,试图通过简单地向主键列添加索引来加快ClickHouse查询的自然冲动通常是不正确的。只有在研究了其他替代方法(如修改主键(请参阅如何选择主键)、使用投影或使用物化视图)之后,才应该使用这种高级功能。即使跳数索引是合适的,也经常需要仔细调优索引和表。

在大多数情况下,一个有用的跳数索引需要主键和目标非主键列/表达式之间有很强的相关性。如果不存在相关性(如上图所示),那么在包含数千个值的块中,至少有一行满足过滤条件的可能性很高,并且很少有块会被跳过。相反,如果主键的值范围(比如一天中的时间)与潜在索引列中的值(比如电视观众的年龄)密切相关,那么minmax类型的索引可能是有益的。请注意,在插入数据时,可以通过在排序/ORDER BY键中包含额外的列,或者通过在插入时对与主键关联的值进行分组的方式来批处理插入,从而增加这种相关性。例如,可以将特定site_id的所有事件分组并由ingest过程插入到一起,即使主键是包含来自大量站点的事件的时间戳。这将导致许多只包含少数站点id的颗粒,因此在通过特定site_id值进行搜索时可以跳过许多块。

跳数索引的另一个很好的候选对象是高基数表达式,其中任何一个值在数据中都是相对稀疏的。一个例子可能是跟踪API请求中的错误代码的可观察性平台。某些错误代码虽然在数据中很少见,但可能对搜索特别重要。error_code列上的集合跳过索引将允许绕过绝大多数不包含错误的块,从而显著改进以错误为中心的查询。

最后,关键的最佳实践是测试、测试、再测试。同样,与用于搜索文档的b-树辅助索引或倒排索引不同,跳数索引行为不容易预测。将它们添加到表中会在数据读取和由于各种原因无法从索引中获益的查询上产生很在的成本。它们应该始终在真实世界的数据类型上进行测试,并且测试应该包括类型、粒度大小和其他参数的变化。测试通常会揭示一些模式和陷阱,这些模式和陷阱在单纯的思想实验中并不明显。

7、SQL 参考中的 Data Skipping Indexes

索引声明位于CREATE查询的columns部分。

INDEX index_name expr TYPE type(...) [GRANULARITY granularity_value]

对于来自*MergeTree族的表,可以指定数据跳过索引。

这些索引聚合了关于块上指定表达式的一些信息,这些块由granularity_value粒度组成(粒度的大小是使用表引擎中的index_granularity设置指定的)。然后在SELECT查询中使用这些聚合,通过跳过不能满足where查询的大数据块来减少从磁盘读取的数据量。

GRANULARITY子句可以省略,granularity_value的默认值为1

例子:

CREATE TABLE table_name
(u64 UInt64,i32 Int32,s String,...INDEX idx1 u64 TYPE bloom_filter GRANULARITY 3,INDEX idx2 u64 * i32 TYPE minmax GRANULARITY 3,INDEX idx3 u64 * length(s) TYPE set(1000) GRANULARITY 4
) ENGINE = MergeTree()
...

在以下查询中,ClickHouse可以使用示例中的索引来减少从磁盘读取的数据量:

SELECT count() FROM table WHERE u64 == 10;
SELECT count() FROM table WHERE u64 * i32 >= 1234
SELECT count() FROM table WHERE u64 * length(s) == 1234

跳数索引也可以在复合列上创建:

-- on columns of type Map:
INDEX map_key_index mapKeys(map_column) TYPE bloom_filter
INDEX map_value_index mapValues(map_column) TYPE bloom_filter-- on columns of type Tuple:
INDEX tuple_1_index tuple_column.1 TYPE bloom_filter
INDEX tuple_2_index tuple_column.2 TYPE bloom_filter-- on columns of type Nested:
INDEX nested_1_index col.nested_col1 TYPE bloom_filter
INDEX nested_2_index col.nested_col2 TYPE bloom_filter

用户可以创建UDF来估计ngrambf_v1的参数集。查询语句如下:

CREATE FUNCTION bfEstimateFunctions [ON CLUSTER cluster]
AS
(total_nubmer_of_all_grams, size_of_bloom_filter_in_bits) -> round((size_of_bloom_filter_in_bits / total_nubmer_of_all_grams) * log(2));CREATE FUNCTION bfEstimateBmSize [ON CLUSTER cluster]
AS
(total_nubmer_of_all_grams,  probability_of_false_positives) -> ceil((total_nubmer_of_all_grams * log(probability_of_false_positives)) / log(1 / pow(2, log(2))));CREATE FUNCTION bfEstimateFalsePositive [ON CLUSTER cluster]
AS
(total_nubmer_of_all_grams, number_of_hash_functions, size_of_bloom_filter_in_bytes) -> pow(1 - exp(-number_of_hash_functions/ (size_of_bloom_filter_in_bytes / total_nubmer_of_all_grams)), number_of_hash_functions);CREATE FUNCTION bfEstimateGramNumber [ON CLUSTER cluster]
AS
(number_of_hash_functions, probability_of_false_positives, size_of_bloom_filter_in_bytes) -> ceil(size_of_bloom_filter_in_bytes / (-number_of_hash_functions / log(1 - exp(log(probability_of_false_positives) / number_of_hash_functions))))

要使用这些函数,我们至少需要指定两个参数。例如,如果粒度中有4300 ngrams ,我们期望误报小于0.0001。其他参数可以通过执行以下查询来估计:

--- estimate number of bits in the filter
SELECT bfEstimateBmSize(4300, 0.0001) / 8 as size_of_bloom_filter_in_bytes;┌─size_of_bloom_filter_in_bytes─┐
│                         10304 │
└───────────────────────────────┘--- estimate number of hash functions
SELECT bfEstimateFunctions(4300, bfEstimateBmSize(4300, 0.0001)) as number_of_hash_functions┌─number_of_hash_functions─┐
│                       13 │
└──────────────────────────┘

当然,您也可以使用这些函数根据其他条件估计参数。功能指的是这里的内容。

特殊用途

  • 实验性索引支持近似最近邻(ANN)搜索。详情请看这里。
  • 一个实验性的倒排索引,支持全文搜索。详情请看这里。

函数支持

WHERE子句中的条件包含对列进行操作的函数的调用。如果列是索引的一部分,ClickHouse在执行函数时尝试使用该索引。ClickHouse支持使用索引的不同函数子集。

类型set的索引可以被所有函数使用。支持的其他索引类型请参考

扩展

布隆(Bloom Filter)过滤器——全面讲解,建议收藏

增加元素
往布隆过滤器增加元素,添加的key需要根据k个无偏hash函数计算得到多个hash值,然后对数组长度进行取模得到数组下标的位置,然后将对应数组下标的位置的值置为1

  • 通过k个无偏hash函数计算得到k个hash值
  • 依次取模数组长度,得到数组索引
  • 将计算得到的数组索引下标位置数据修改为1

例如,key = Liziba,无偏hash函数的个数k=3,分别为hash1、hash2、hash3。三个hash函数计算后得到三个数组下标值,并将其值修改为1.
如图所示:
在这里插入图片描述
查询元素:
布隆过滤器最大的用处就在于判断某样东西一定不存在或者可能存在,而这个就是查询元素的结果。其查询元素的过程如下:

  • 通过k个无偏hash函数计算得到k个hash值
  • 依次取模数组长度,得到数组索引
  • 判断索引处的值是否全部为1,如果全部为1则存在(这种存在可能是误判),如果存在一个0则必定不存在

相关文章:

ClickHouse 指南(三)最佳实践 -- 跳数索引

Data Skipping Indexes Data Skipping Indexes 2 1、简介 影响ClickHouse查询性能的因素很多。在大多数情况下&#xff0c;关键因素是ClickHouse在计算查询WHERE子句条件时是否可以使用主键。因此&#xff0c;选择适用于最常见查询模式的主键对于有效的表设计至关重要。 然…...

Mybatis总结--传参二

#叫做占位符 Mybatis是封装的JDBC 增强版 内部还是用的jdbc 每遇到一个#号 这里就会变为&#xff1f;占位符 一个#{}就是对应一个问号 一个占位符 用这个对象执行sql语句没有sql注入的风险 八、多个参数-使用Param 当 Dao 接口方法有多个参数&#xff0c;需要通过名称使…...

2024年数字化转型风口趋势大赏

人工智能和自动化确实为提高效率和数据驱动的见解提供了巨大的潜力&#xff0c;但这些技术无法完全取代人类技能和情境决策。在混合模型中将人工智能功能与人类专业知识相结合的企业将实现最大的效益。 随着人工智能和自动化的不断发展&#xff0c;企业必须调整其战略、流程和人…...

某款服务器插上4张TDP功耗75瓦PCIE卡无法开机的调试过程

1.服务器厂家说这款服务器测过别家的4卡&#xff0c;所以一开始并没有怀疑服务器硬件有问题 2.拔掉另外三张&#xff0c;只保留cpu0对应的riser0 slot0上的一张卡&#xff0c;仍然无法开机。 3.怀疑是这张pcie卡bar空间太大导致。换另一款bar空间小的卡&#xff0c;仍然无法开…...

数据结构与算法——排序算法

目录 文章目录 前言 一.排序的基本概念 1.什么是就地排序 2.什么是内部排序和外部排序 3.什么是稳定排序 4.判定一个排序算法的是稳定的 二.插入排序算法 1.直接插入排序 1.1基本思想 1.2复杂度 1.3稳定性 1.4代码演示 2.折半插入排序 2.1基本思想 2.2性能 3.…...

阿里巴巴alibaba API商品详情接口系列(商品属性,价格,主图)阿里巴巴alibaba根据ID取商品详情 API 返回值说明

阿里巴巴Alibaba的API商品详情接口系列通常用于获取指定商品的详细信息&#xff0c;包括商品属性、价格、主图等。与来赞达Lazada的API类似&#xff0c;具体的返回值可能会根据API的版本和阿里巴巴平台的更新而有所不同。 以下是一个假设的阿里巴巴API商品详情接口的返回值示例…...

lcd画圆

//****************************************************************** //函数名&#xff1a; _draw_circle_8 //功能&#xff1a; 8对称性画圆算法(内部调用) //输入参数&#xff1a;(xc,yc) :圆中心坐标 // (x,y):光标相对于圆心的坐标 // c:填…...

React组件详解

React组件分为两大类 1.函数组件 2.类组件&#xff08;最常用&#xff09; 组件化 import ReactDom from "react-dom";// // 1.通过函数创建一个组件 // 2.函数名字必须大写开头 // 3.函数必须有返回值 function Func1() {return <h2>这是一个基础组件</h…...

C++面试:内存溢出、内存泄漏的原因与解决

目录 内存溢出&#xff08;Memory Overflow&#xff09; 内存溢出介绍 解决内存溢出问题的方法 内存泄漏&#xff08;Memory Leak&#xff09; 内存泄露基础 解决内存泄漏问题的方法 内存溢出&#xff08;Memory Overflow&#xff09; 内存溢出介绍 内存溢出是指程序在执…...

【Java程序员面试专栏 算法思维】二 高频面试算法题:二分查找

一轮的算法训练完成后,对相关的题目有了一个初步理解了,接下来进行专题训练,以下这些题目就是汇总的高频题目,本篇主要聊聊二分查找,包括基础二分,寻找目标值的左右边界,搜索旋转数组以及波峰,以及x的平方根问题,所以放到一篇Blog中集中练习 题目关键字解题思路时间空…...

kaldi 详细安装教程、PyTorch-Kaldi、TIMIT下载、Librispeech下载

kaldi 详细安装教程 本kaldi 安装教程 转载于该链接kaldi 详细安装教程 安装系统依赖&#xff08;如果经常使用linux 服务器&#xff0c;一般都会有&#xff09; apt-get updateapt-get install -y --no-install-recommends g make automake autoconf bzip2 unzip wget sox …...

EtherCAT 转 ModbusTCP 网关

功能概述 本产品是 EtherCAT 和 Modbus TCP 网关&#xff0c;使用数据映射方式工作。 本产品在 EtherCAT 侧作为 EtherCAT 从站&#xff0c;接 TwinCAT 、CodeSYS 、PLC 等&#xff1b;在 ModbusTCP 侧做为 ModbusTCP 主站&#xff08;Client&#xff09;或从站&#xff08;Se…...

iMazing2024Windows和Mac的iOS设备管理软件(可以替代iTunes进行数据备份和管理)

iMazing2024是一款兼容 Windows 和 Mac 的 iOS 设备管理软件&#xff0c;可以替代 iTunes 进行数据备份和管理。以下是一些 iMazing 的主要功能和优点&#xff1a; 数据备份和恢复&#xff1a;iMazing 提供了强大的数据备份和恢复功能&#xff0c;可以备份 iOS 设备上的各种数据…...

carpower

车载android 电源管理 车载音响电源管理器_definitely的技术博客_51CTO博客...

数据结构2月25日

第一道&#xff1a; 第二道&#xff1a; 1、插入到prev和next中间 1.new(struct list_head*)malloc(sizeof(struct list_head*)); if(newNULL) { printf("失败\n"); return; } new->nextprev->next; prev->nextnew; return; 2、删除prve和next…...

改进 RAG:自查询检索

原文地址&#xff1a;Improving RAG: Self Querying Retrieval 2024 年 2 月 11 日 让我们来解决构建 RAG 系统时的一个大问题。 我们不能依赖语义搜索来完成每个检索任务。只有当我们追求单词的含义和意图时&#xff0c;语义搜索才有意义。 But in case&#xff0c;我们正…...

【Git企业实战开发】Git常用开发流操作总结

【Git企业实战开发】Git常用开发流操作总结 大家好 我是寸铁&#x1f44a; 总结了一篇Git常用开发流操作总结的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 现在刚做项目的伙伴&#xff0c;可能你之前学过git&#xff0c;但是一实战发现不熟悉 没关系&#xff0c;看寸铁这篇…...

vue2+element医院安全(不良)事件报告管理系统源代码

目录 安全不良事件类型 源码技术栈 医院安全&#xff08;不良&#xff09;事件报告管理系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件…...

leetcode初级算法(python)- 字符串

文章目录 1.反转字符串常规算法pythonic 算法2.整数反转数学法字符串法3.字符串中的第一个唯一字符pythonic算法哈希算法4.有效的字母异位词常规算法进阶算法5.最长公共前缀1.反转字符串 输入:[‘h’,‘e’,‘l’,‘l’,‘o’] 输出:[‘o’,‘l’,‘l’,‘e’,‘h’]...

Python 鼠标模拟

鼠标模拟即&#xff1a;通过python 进行模拟鼠标操作 引入类库 示例如下&#xff1a; import win32api import win32con import time 设置鼠标位置 设置鼠标位置为窗口中的回收站。 示例如下&#xff1a; # 设置鼠标的位置 win32api.SetCursorPos([30, 40]) 双击图标 设置…...

Linux进程 ----- 信号处理

前言 从信号产生到信号保存&#xff0c;中间经历了很多&#xff0c;当操作系统准备对信号进行处理时&#xff0c;还需要判断时机是否 “合适”&#xff0c;在绝大多数情况下&#xff0c;只有在 “合适” 的时机才能处理信号&#xff0c;即调用信号的执行动作。 一、信号的处理…...

【数位】【数论】【分类讨论】2999. 统计强大整数的数目

作者推荐 动态规划的时间复杂度优化 本文涉及知识点 数位 数论 LeetCode2999. 统计强大整数的数目 给你三个整数 start &#xff0c;finish 和 limit 。同时给你一个下标从 0 开始的字符串 s &#xff0c;表示一个 正 整数。 如果一个 正 整数 x 末尾部分是 s &#xff08…...

MongoDB聚合运算符:$atan2

$atan2用来计算反正切&#xff0c;返回指定表达式的反正切值&#xff0c;与$antan的区别主要是参数不同。 语法 { $atan2: [<expression1>, <expression1>] }<expression>为可被解析为数值的表达式$atan2返回弧度&#xff0c;使用$radiansToDegrees运算符可…...

敏捷开发最佳实践:价值维度实践案例之ABTest中台化

22年敏捷白皮书调研发现&#xff0c;仅有14%的企业部分实现价值管理闭环&#xff0c;8%的企业能够做到企业战略和业务目标与价值管理紧密结合。这一现象说明了大部分中国企业还不能在敏捷实践中实现需求价值的体系化及多维度价值度量&#xff0c;因此推广优秀的敏捷实践至关重要…...

爬虫基本库的使用(requests库的详细解析)

注&#xff1a;本文一共4万多字&#xff0c;希望读者能耐心读完&#xff01;&#xff01;&#xff01; 前面,我们了解了urllib库的基本用法&#xff08;爬虫基本库的使用(urllib库的详细解析)-CSDN博客&#xff09;。其中&#xff0c;确实又不方便的地方。例如处理网页验证…...

QT实现串口通信

一.Qt串口通信 Qt提供了两个关于串口通信的C类&#xff0c;分别是QSerialPort和QSerialPortInfo。 QSerialPort类提供了操作串口的各种接口。 QSerialPortInfo是一个辅助类&#xff0c;可以提供计算机中可用的串口的各种信息。 QSerialPortInfo Class用于提供外部串行端口的…...

微信小程序 --- 通用模块封装(showToast,showModal ,本地存储)

目录 01. 为什么进行模块封装 02. 消息提示模块封装 03. 模态对话框封装 04. 封装本地存储 API 05. 拓展:封装异步存储API优化代码 01. 为什么进行模块封装 在进行项目开发的时候&#xff0c;我们经常的会频繁的使用到一些 API&#xff0c; 例如&#xff1a;wx.showToast…...

基于springboot+vue的音乐网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…...

pclpy 最小二乘法拟合平面

pclpy 最小二乘法拟合平面 一、算法原理二、代码三、结果1.左边原点云、右边最小二乘法拟合平面后点云投影 四、相关数据 一、算法原理 平面方程的一般表达式为&#xff1a; A x B y C z D 0 ( C ≠ 0 ) Ax By Cz D 0 \quad (C\neq0) AxByCzD0(C0) 即&#xff1a; …...

蓝桥杯备战刷题(自用)

1.被污染的支票 #include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; int main() {int n;cin>>n;vector<int>L;map<int,int>mp;bool ok0;int num;for(int i1;i<n;i){cin>>nu…...

Python习题详解

练习&#xff1a; 1&#xff0c;计算100以内奇数的和 #计算100以内所有奇数的和 sum 0 # n 1 # while n < 100: # # sum sum n # sum n # # n n 2 # n 2 # print(sum) n 99 #求偶数时n 100 while n > 0:sum n# n n - 2n - 2 print(sum)2&#xff0c;打印直…...

绩效考核利器:Excel报表模板,解锁企业高效员工评价新境界

一、背景与目标 在现今的企业管理中&#xff0c;绩效考核是一项至关重要的任务。它旨在评估员工的工作表现&#xff0c;激励员工积极进取&#xff0c;同时也是制定薪酬、晋升、培训等决策的重要依据。为了满足这一需求&#xff0c;我们设计了一款绩效考核Excel报表模板&#x…...

如何使用Lychee+cpolar搭建本地私人图床并实现远程访问存储图片

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 图床作为图片集中存放的服务网站&#xff0c;可以看做是云存储的一部分&#xff0c;既可…...

跨境支付介绍

1、跨境电商定义和分类&#xff1b; 2、国际贸易清结算&#xff1b; 3、跨境支付&#xff1b; 1、跨境电商定义和分类 跨境电商业务简单说就是指不同国家地域的主体通过电子商务进行交易的一种业务模式。同传统的电商不同&#xff0c;交易双方属于不同的国家。因此&#xff0…...

如何在Linux搭建MinIO服务并实现无公网ip远程访问内网管理界面

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…...

Cortex-M可以跑Linux操作系统吗?

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; Cortex-M系列微控制器主要设计…...

日志系统项目(2)项目实现(实用工具类、日志等级类、日志消息类、日志格式化输出类)

前面的文章中我们讲述了日志系统项目的前置知识点&#xff0c;再本文中我们将开始日志项目的细节实现。 日志系统框架设计 本项目实现的是一个多日志器日志系统&#xff0c;主要实现的功能是让程序员能够轻松的将程序运行日志信息落地到指定的位置&#xff0c;且支持同步与异…...

剑指offer面试题19 二叉树的镜像

考察点 树的遍历知识点 题目 分析 我们分析算法题目的思路基本上都是归纳法&#xff0c;即通过举一些普通的例子来推理出算法流程&#xff0c;而画图又是举例子的常用手段&#xff0c;比如针对树或者链表画画图&#xff0c;针对数字类的举一些数字的例子寻找规律&#xff0c…...

SpringCloud Alibaba 2022之Nacos学习

SpringCloud Alibaba 2022使用 SpringCloud Alibaba 2022需要Spring Boot 3.0以上的版本&#xff0c;同时JDK需要是17及以上的版本。具体的可以看官网的说明。 Spring Cloud Alibaba版本说明 环境搭建 这里搭建的是一个聚合项目。项目结构如下&#xff1a; 父项目的pom.xm…...

js之数组遍历

for 可以用来遍历数组、字符串、类数组、DOM节点&#xff0c;可以更改原数组&#xff0c;可以使用break、continue 跳出循环 return 只能在函数内部使用 for(声明循环变量&#xff1b;判断循环条件&#xff1b;更新循环变量){循环体 }forEach 参数&#xff08;当前元素&#x…...

极狐GitLab 16.9 重磅发布,快来 pick 你心仪的功能吧~【五】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 沿袭我们的月度发版机制&#xff0c;今天我们正式发布极狐GitL…...

如何在本地部署密码管理软件bitwarden并结合cpolar实现远程同步

文章目录 1. 拉取Bitwarden镜像2. 运行Bitwarden镜像3. 本地访问4. 群晖安装Cpolar5. 配置公网地址6. 公网访问Bitwarden7. 固定公网地址8. 浏览器密码托管设置 Bitwarden是一个密码管理器应用程序&#xff0c;适用于在多个设备和浏览器之间同步密码。自建密码管理软件bitwarde…...

DT DAY3 信号和槽

作业&#xff1a; 1> 思维导图 2> 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 btn3 new QPushButton("按钮3",this);btn3->resize(ui->btn2->width(),ui->b…...

Spring、SpringBoot、SpringCloud三者的区别

Spring、Spring Boot 和 Spring Cloud 是构建企业级 Java 应用程序的不同层次的框架和工具。下面详细介绍它们之间的区别&#xff1a; 1. Spring框架&#xff1a; 概述&#xff1a; Spring 是一个全功能的企业级 Java 框架&#xff0c;提供了依赖注入、面向切面编程、事务管理…...

leetcode:46.全排列

1.什么是排列&#xff1f; 有顺序&#xff01;&#xff01; 2.树形结构&#xff1a; 使用used数组进行标记取过的元素&#xff0c;一个元素一个元素地进行取值&#xff0c;取完之后将used数组进行标记。 3.代码实现&#xff1a;&#xff08;循环从i0开始&#xff0c;而不是…...

基于STM32的宠物箱温度湿度监控系统

基于STM32的宠物箱温度湿度监控系统 一、引言 随着人们生活水平的提高,养宠物已经成为越来越多人的选择。宠物作为家庭的一员,其生活环境和健康状况受到了广泛关注。温度和湿度是影响宠物舒适度和健康的重要因素之一。因此,开发一款能够实时监控宠物箱温度和湿度的系统具有…...

《高质量的C/C++编程规范》学习

目录 一、编程规范基础知识 1、头文件 2、程序的板式风格 3、命名规则 二、表达式和基本语句 1、运算符的优先级 2、复合表达式 3、if语句 4、循环语句的效率 5、for循环语句 6、switch语句 三、常量 1、#define和const比较 2、常量定义规则 四、函数设计 1、参…...

客户端订阅服务端事件的机制

一、场景描述 产业大脑平台是一个典型的审核系统&#xff0c;用户发布到平台的信息需要经过审核员审核后生效。 用户发布信息->审核员审核信息->用户信息生效&#xff0c;这一流程可能发生在用户的同一次登录周期内。为了使客户端能实时响应信息的状态变化&#xff0c;…...

pulsar入门介绍

概述 Pulsar 是一个多租户、高性能的服务器到服务器消息传递解决方案。Pulsar 最初由 Yahoo 开发&#xff0c;由 Apache 软件基金会管理。 特点 Pulsar 的主要功能如下&#xff1a; 原生支持 Pulsar 实例中的多个集群&#xff0c;可跨集群无缝地复制消息。非常低的发布和端…...

Leetcode 3047. Find the Largest Area of Square Inside Two Rectangles

Leetcode 3047. Find the Largest Area of Square Inside Two Rectangles 1. 解题思路2. 代码实现 题目链接&#xff1a;3047. Find the Largest Area of Square Inside Two Rectangles 1. 解题思路 这道题倒是没啥特别的思路&#xff0c;直接暴力求解就是了&#xff0c;因此…...