ElasticSearch深度分页解决方案

news2024/11/22 7:12:43

文章目录

    • 概要
    • ElasticSearch介绍
    • es分页方法
        • es分页性能对比表
        • 方案对比
    • From/Size参数
    • 深度分页问题
    • Scroll
      • #性能对比
        • 向前翻页
    • 总结
    • 个人思考

概要

好久没更新文章了,最近研究了一下es的深分页解决方案。和大家分享一下,祝大家国庆节快乐。

ElasticSearch介绍

Elasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎,在使用过程中,有一些典型的使用场景,比如分页、遍历等。

在使用关系型数据库中,我们被告知要注意甚至被明确禁止使用深度分页,同理,在 Elasticsearch 中,也应该尽量避免使用深度分页。

这篇文章主要介绍 Elasticsearch 中分页相关内容!

es分页方法

  • From/Size参数
  • Scroll
  • Scroll Scan
  • Sliced Scroll
  • Search After
es分页性能对比表
分页方式1~1049000~4901099000~999010
from + size8ms30ms117ms
Scroll7ms66ms36ms
Search After8ms8ms7ms
方案对比
方案原理优点缺点使用场景
from + size类似 msql的 limit 0,100; limit from,size灵活性好,实现简单,适合浅分页无法实现深度分页问题,当查询数量超过10000就会报错top10000以内的查询
Scroll首次查询会在内存中保存一个历史快照以及游标(scroll_id),记录当前消息查询的终止位置,下次查询的时候将基于游标进行消费(不管while语句循环多少次,scrollid在设置的时效内,使用的是同一个),不具备实时性,一般是用于大量数据导出。适合深分页无法反应数据的实时性(快照版本),维护成本高,需要维护一个 scroll_id最适合离线场景,海量数据的导出(比如笔者刚遇到的将es中20w的数据导入到excel),需要查询海量结果集的数据
Search Afterstep1:在查询第1页的时候,设置全局唯一性的字段进行组合排序;step2:查询数据之后,取出最后一笔数据的sort值,传到search_after进行查询;step3:基于上一笔的sort值,查询排在它之后的数据,以此来实现分页不能够随机跳转分页,只能是一页一页的向后翻(当有新数据进来,也能实时查询到),并且需要至少指定一个唯一不重复字段来排序(一般是_id和时间字段)海量数据的实时分页性能最好,适合深分页,能够反映数据的实时变更

From/Size参数

在ES中,分页查询默认返回最顶端的10条匹配hits。

如果需要分页,需要使用from和size参数。

  • from参数定义了需要跳过的hits数,默认为0;

  • size参数定义了需要返回的hits数目的最大值。

一个基本的ES查询语句是这样的:

	POST /my_index/my_type/_search
	{
	    "query": { "match_all": {}},
	    "from": 100,
	    "size":  10
	}

上面的查询表示从搜索结果中取第100条开始的10条数据。

** 那么,这个查询语句在ES集群内部是怎么执行的呢?**

在ES中,搜索一般包括两个阶段,query 和 fetch 阶段,可以简单的理解,query 阶段确定要取哪些doc,fetch 阶段取出具体的 doc。

Query阶段

图片
如上图所示,描述了一次搜索请求的 query 阶段:·
在这里插入图片描述

Client 发送一次搜索请求,node1 接收到请求,然后,node1 创建一个大小为from + size的优先级队列用来存结果,我们管 node1 叫 coordinating node。
coordinating node将请求广播到涉及到的 shards,每个 shard 在内部执行搜索请求,然后,将结果存到内部的大小同样为from + size 的优先级队列里,可以把优先级队列理解为一个包含top N结果的列表。
每个 shard 把暂存在自身优先级队列里的数据返回给 coordinating node,coordinating node 拿到各个 shards 返回的结果后对结果进行一次合并,产生一个全局的优先级队列,存到自身的优先级队列里。
在上面的例子中,coordinating node 拿到(from + size) * 6条数据,然后合并并排序后选择前面的from + size条数据存到优先级队列,以便 fetch 阶段使用。

另外,各个分片返回给 coordinating node 的数据用于选出前from + size条数据,所以,只需要返回唯一标记 doc 的_id以及用于排序的_score即可,这样也可以保证返回的数据量足够小。

coordinating node 计算好自己的优先级队列后,query 阶段结束,进入 fetch 阶段。


Fetch阶段


query 阶段知道了要取哪些数据,但是并没有取具体的数据,这就是 fetch 阶段要做的。
在这里插入图片描述
上图展示了 fetch 过程:

coordinating node 发送 GET 请求到相关shards。
shard 根据 doc 的_id取到数据详情,然后返回给 coordinating node。
coordinating node 返回数据给 Client。
coordinating node 的优先级队列里有from + size 个_doc _id,但是,在 fetch 阶段,并不需要取回所有数据,在上面的例子中,前100条数据是不需要取的,只需要取优先级队列里的第101到110条数据即可。

需要取的数据可能在不同分片,也可能在同一分片,coordinating node 使用 「multi-get」 来避免多次去同一分片取数据,从而提高性能。

「这种方式请求深度分页是有问题的:」

我们可以假设在一个有 5 个主分片的索引中搜索。当我们请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给 协调节点 ,协调节点对 50 个结果排序得到全部结果的前 10 个。

现在假设我们请求第 1000 页—结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个结果以外。然后协调节点对全部 50050 个结果排序最后丢弃掉这些结果中的 50040 个结果。

「对结果排序的成本随分页的深度成指数上升。」

「注意1:」

size的大小不能超过index.max_result_window这个参数的设置,默认为10000。

如果搜索size大于10000,需要设置index.max_result_window参数

PUT _settings
{
    "index": {
        "max_result_window": "10000000"
    }
}  

[^1] _doc将在未来的版本移除,详见:
https://www.elastic.co/cn/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0
https://elasticsearch.cn/article/158
图片

深度分页问题

Elasticsearch 的From/Size方式提供了分页的功能,同时,也有相应的限制。

举个例子,一个索引,有10亿数据,分10个 shards,然后,一个搜索请求,from=1000000,size=100,这时候,会带来严重的性能问题:CPU,内存,IO,网络带宽。

在 query 阶段,每个shards需要返回 1000100 条数据给 coordinating node,而 coordinating node 需要接收10 * 1000,100 条数据,即使每条数据只有 _doc _id 和 _score,这数据量也很大了?

「在另一方面,我们意识到,这种深度分页的请求并不合理,因为我们是很少人为的看很后面的请求的,在很多的业务场景中,都直接限制分页,比如只能看前100页。」

比如,有1千万粉丝的微信大V,要给所有粉丝群发消息,或者给某省粉丝群发,这时候就需要取得所有符合条件的粉丝,而最容易想到的就是利用 from + size 来实现,不过,这个是不现实的,这时,可以采用 Elasticsearch 提供的其他方式来实现遍历。

深度分页问题大致可以分为两类:

「随机深度分页:随机跳转页面」
「滚动深度分页:只能一页一页往下查询」
「下面介绍几个官方提供的深度分页方法」

Scroll


Scroll遍历数据


我们可以把scroll理解为关系型数据库里的cursor,因此,scroll并不适合用来做实时搜索,而更适合用于后台批处理任务,比如群发。

这个分页的用法,「不是为了实时查询数据」,而是为了「一次性查询大量的数据(甚至是全部的数据」)。

因为这个scroll相当于维护了一份当前索引段的快照信息,这个快照信息是你执行这个scroll查询时的快照。在这个查询后的任何新索引进来的数据,都不会在这个快照中查询到。

但是它相对于from和size,不是查询所有数据然后剔除不要的部分,而是记录一个读取的位置,保证下一次快速继续读取。

不考虑排序的时候,可以结合SearchType.SCAN使用。

scroll可以分为初始化和遍历两部,初始化时将「所有符合搜索条件的搜索结果缓存起来(注意,这里只是缓存的doc_id,而并不是真的缓存了所有的文档数据,取数据是在fetch阶段完成的)」,可以想象成快照。

在遍历时,从这个快照里取数据,也就是说,在初始化后,对索引插入、删除、更新数据都不会影响遍历结果。

「基本使用」

POST /twitter/tweet/_search?scroll=1m
{
    "size": 100,
    "query": {
        "match" : {
            "title" : "elasticsearch"
        }
    }
}

初始化指明 index 和 type,然后,加上参数 scroll,表示暂存搜索结果的时间,其它就像一个普通的search请求一样。

会返回一个_scroll_id,_scroll_id用来下次取数据用。

「遍历」

POST /_search?scroll=1m
{
    "scroll_id":"XXXXXXXXXXXXXXXXXXXXXXX I am scroll id XXXXXXXXXXXXXXX"
}

这里的scroll_id即 上一次遍历取回的_scroll_id或者是初始化返回的_scroll_id,同样的,需要带 scroll 参数。

重复这一步骤,直到返回的数据为空,即遍历完成。

「注意,每次都要传参数 scroll,刷新搜索结果的缓存时间」。另外,「不需要指定 index 和 type」。

设置scroll的时候,需要使搜索结果缓存到下一次遍历完成,「同时,也不能太长,毕竟空间有限。」

「优缺点」

缺点:

「scroll_id会占用大量的资源(特别是排序的请求)」
同样的,scroll后接超时时间,频繁的发起scroll请求,会出现一些列问题。
「是生成的历史快照,对于数据的变更不会反映到快照上。」
「优点:」

适用于非实时处理大量数据的情况,比如要进行数据迁移或者索引变更之类的。

Scroll Scan
ES提供了scroll scan方式进一步提高遍历性能,但是scroll scan不支持排序,因此scroll scan适合不需要排序的场景

「基本使用」

Scroll Scan 的遍历与普通 Scroll 一样,初始化存在一点差别。

POST /my_index/my_type/_search?search_type=scan&scroll=1m&size=50
{
 "query": { "match_all": {}}
}

需要指明参数:

search_type:赋值为scan,表示采用 Scroll Scan 的方式遍历,同时告诉 Elasticsearch 搜索结果不需要排序。
scroll:同上,传时间。
size:与普通的 size 不同,这个 size 表示的是每个 shard 返回的 size 数,最终结果最大为 number_of_shards * size。
「Scroll Scan与Scroll的区别」

Scroll-Scan结果「没有排序」,按index顺序返回,没有排序,可以提高取数据性能。
初始化时只返回 _scroll_id,没有具体的hits结果
size控制的是每个分片的返回的数据量,而不是整个请求返回的数据量。
Sliced Scroll
如果你数据量很大,用Scroll遍历数据那确实是接受不了,现在Scroll接口可以并发来进行数据遍历了。

每个Scroll请求,可以分成多个Slice请求,可以理解为切片,各Slice独立并行,比用Scroll遍历要快很多倍。

POST /index/type/_search?scroll=1m
{
    "query": { "match_all": {}},
    "slice": {
        "id": 0,
        "max": 5
    }   
}

POST ip:port/index/type/_search?scroll=1m
{
    "query": { "match_all": {}},
    "slice": {
        "id": 1,
        "max": 5
    }   
}

上边的示例可以单独请求两块数据,最终五块数据合并的结果与直接scroll scan相同。

其中max是分块数,id是第几块。


官方文档中建议max的值不要超过shard的数量,否则可能会导致内存爆炸。


Search After
Search_after是 ES 5 新引入的一种分页查询机制,其原理几乎就是和scroll一样,因此代码也几乎是一样的。

「基本使用:」

第一步:

POST twitter/_search
{
    "size": 10,
    "query": {
        "match" : {
            "title" : "es"
        }
    },
    "sort": [
        {"date": "asc"},
        {"_id": "desc"}
    ]
}

返回出的结果信息 :

{
      "took" : 29,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 5,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [
          {
            ...
            },
            "sort" : [
              ...
            ]
          },
          {
            ...
            },
            "sort" : [
              124648691,
              "624812"
            ]
          }
        ]
      }
    }

上面的请求会为每一个文档返回一个包含sort排序值的数组。

这些sort排序值可以被用于search_after参数里以便抓取下一页的数据。

比如,我们可以使用最后的一个文档的sort排序值,将它传递给search_after参数:

GET twitter/_search
{
    "size": 10,
    "query": {
        "match" : {
            "title" : "es"
        }
    },
    "search_after": [124648691, "624812"],
    "sort": [
        {"date": "asc"},
        {"_id": "desc"}
    ]
}

若我们想接着上次读取的结果进行读取下一页数据,第二次查询在第一次查询时的语句基础上添加search_after,并指明从哪个数据后开始读取。

「基本原理」

es维护一个实时游标,它以上一次查询的最后一条记录为游标,方便对下一页的查询,它是一个无状态的查询,因此每次查询的都是最新的数据。

由于它采用记录作为游标,因此「SearchAfter要求doc中至少有一条全局唯一变量(每个文档具有一个唯一值的字段应该用作排序规范)」

「优缺点」

「优点:」

无状态查询,可以防止在查询过程中,数据的变更无法及时反映到查询中。
不需要维护scroll_id,不需要维护快照,因此可以避免消耗大量的资源。
「缺点:」

由于无状态查询,因此在查询期间的变更可能会导致跨页面的不一值。
排序顺序可能会在执行期间发生变化,具体取决于索引的更新和删除。
至少需要制定一个唯一的不重复字段来排序。
它不适用于大幅度跳页查询,或者全量导出,对第N页的跳转查询相当于对es不断重复的执行N次search after,而全量导出则是在短时间内执行大量的重复查询。
SEARCH_AFTER不是自由跳转到任意页面的解决方案,而是并行滚动多个查询的解决方案。

总结
分页方式 性能 优点 缺点 场景
from + size 低 灵活性好,实现简单 深度分页问题 数据量比较小,能容忍深度分页问题
scroll 中 解决了深度分页问题 无法反应数据的实时性(快照版本)维护成本高,需要维护一个 scroll_id 海量数据的导出需要查询海量结果集的数据
search_after 高 性能最好不存在深度分页问题能够反映数据的实时变更 实现复杂,需要有一个全局唯一的字段连续分页的实现会比较复杂,因为每一次查询都需要上次查询的结果,它不适用于大幅度跳页查询 海量数据的分页
ES7版本变更
参照:https://www.elastic.co/guide/en/elasticsearch/reference/master/paginate-search-results.html#scroll-search-results

在7.*版本中,ES官方不再推荐使用Scroll方法来进行深分页,而是推荐使用带PIT的search_after来进行查询;

从7.*版本开始,您可以使用SEARCH_AFTER参数通过上一页中的一组排序值检索下一页命中。

使用SEARCH_AFTER需要多个具有相同查询和排序值的搜索请求。

如果这些请求之间发生刷新,则结果的顺序可能会更改,从而导致页面之间的结果不一致。

为防止出现这种情况,您可以创建一个时间点(PIT)来在搜索过程中保留当前索引状态。

POST /my-index-000001/_pit?keep_alive=1m
返回一个PIT ID:
{
  "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
}

在搜索请求中指定PIT:

GET /_search
{
  "size": 10000,
  "query": {
    "match" : {
      "user.id" : "elkbee"
    }
  },
  "pit": {
     "id":  "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==", 
     "keep_alive": "1m"
  },
  "sort": [ 
    {"@timestamp": {"order": "asc", "format": "strict_date_optional_time_nanos", "numeric_type" : "date_nanos" }}
  ]
}

#性能对比

分别分页获取1 - 10,49000 - 49010,99000 - 99010范围各10条数据(前提10w条),性能大致是这样:
图片

向前翻页
  • 对于向前翻页,ES中没有相应API,但是根据官方说法(https://github.com/elastic/elasticsearch/issues/29449),ES中的向前翻页问题可以通过翻转排序方式来实现即:

  • 对于某一页,正序search_after该页的最后一条数据id为下一页,则逆序search_after该页的第一条数据id则为上一页。
    国内论坛上,有人使用缓存来解决上一页的问题

总结

  1. 如果数据量小(from+size在10000条内),或者只关注结果集的TopN数据,可以使用from/size 分页,简单粗暴
  2. 数据量大,深度翻页,后台批处理任务(数据迁移)之类的任务,使用 scroll 方式
  3. 数据量大,深度翻页,用户实时、高并发查询需求,使用 search after 方式

个人思考

Scroll和search_after原理基本相同,他们都采用了游标的方式来进行深分页。

这种方式虽然能够一定程度上解决深分页问题。但是,它们并不是深分页问题的终极解决方案,深分页问题 ** 必须避免!! **。

对于Scroll,无可避免的要维护scroll_id和历史快照,并且,还必须保证scroll_id的存活时间,这对服务器是一个巨大的负荷。

对于Search_After,如果允许用户大幅度跳转页面,会导致短时间内频繁的搜索动作,这样的效率非常低下,这也会增加服务器的负荷,同时,在查询过程中,索引的增删改会导致查询数据不一致或者排序变化,造成结果不准确。

Search_After本身就是一种业务折中方案,它不允许指定跳转到页面,而只提供下一页的功能。

Scroll默认你会在后续将所有符合条件的数据都取出来,所以,它只是搜索到了所有的符合条件的doc_id(这也是为什么官方推荐用doc_id进行排序,因为本身缓存的就是doc_id,如果用其他字段排序会增加查询量),并将它们排序后保存在协调节点(coordinate node),但是并没有将所有数据进行fetch,而是每次scroll,读取size个文档,并返回此次读取的最后一个文档以及上下文状态,用以告知下一次需要从哪个shard的哪个文档之后开始读取。

这也是为什么官方不推荐scroll用来给用户进行实时的分页查询,而是适合于大批量的拉取数据,因为它从设计上就不是为了实时读取数据而设计的。

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

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

相关文章

记一次 .NET 某拍摄监控软件 卡死分析

一:背景 1. 讲故事 今天本来想写一篇 非托管泄露 的生产事故分析,但想着昨天就上了一篇非托管文章,连着写也没什么意思,换个口味吧,刚好前些天有位朋友也找到我,说他们的拍摄监控软件卡死了,让…

Android Shape设置背景

设置背景时&#xff0c;经常这样 android:background“drawable/xxx” 。如果是纯色图片&#xff0c;可以考虑用 shape 替代。 shape 相比图片&#xff0c;减少资源占用&#xff0c;缩减APK体积。 开始使用。 <?xml version"1.0" encoding"utf-8"?…

【STM32单片机】u8g2智能风扇设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用STM32F103C8T6单片机控制器&#xff0c;使用按键、IIC OLED模块、DS18B20温度传感器、直流电机、红外遥控等。 主要功能&#xff1a; 初始化后进入温度显示界面&#xff0c;系统初始状态为手动…

探索视听新纪元: ChatGPT的最新语音和图像功能全解析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f916; 人工智能 AI: &#x1f9e0; Machine …

【我的创作纪念日】使用pix2pixgan实现barts2020数据集的处理(完整版本)

使用pix2pixgan &#xff08;pytorch)实现T1 -> T2的基本代码 使用 https://github.com/eriklindernoren/PyTorch-GAN/ 这里面的pix2pixgan代码进行实现。 进去之后我们需要重新处理数据集&#xff0c;并且源代码里面先训练的生成器&#xff0c;后训练鉴别器。 一般情况下…

亚马逊要求的UL报告的产品标准是什么?如何区分

亚马逊为什么要求电子产品有UL检测报告&#xff1f; 首先&#xff0c;美国是一个对安全要求非常严格的国家&#xff0c;美国本土的所有电子产品生产企业早在很多年前就要求有相关安规检测。 其次&#xff0c;随着亚马逊在全球商业的战略地位不断提高&#xff0c;境外的电子设…

百度资源搜索平台出现:You do not have the proper credential to access this page.怎么办?

Forbidden site not allowed You do not have the proper credential to access this page. If you think this is a server error, please contact the webmaster. 如果你的百度资源平台&#xff0c;点进去出现这个提示&#xff0c;说明您的网站已经被百度清退了。 如果你的网…

队列的分类及用途

队列&#xff08;Queue&#xff09;是一种常见的数据结构&#xff0c;用于存储和管理数据元素。队列通常遵循先进先出&#xff08;FIFO&#xff0c;First-In-First-Out&#xff09;的原则&#xff0c;这意味着最早添加到队列的元素将首先被移除。队列有不同的类型和用途&#x…

VS code本地安装PlantUML

VS code本地安装PlantUML 需要条件vs code安装插件使用常见错误 需要条件 在VS Code上安装PlantUML扩展之前&#xff0c;请确保您具有以下先决条件: : Java与GraphViz(点击可直接跳转下载界面); 安装省略 vs code安装插件 vs code安装以下两个插件&#xff08;PlantUML,Grap…

易云维®智慧工厂数字化管理平台助推工业制造企业数字化转型新动能

近年来&#xff0c;我国正在积极推进工业制造企业数字化转型&#xff0c;工业制造企业数字化转型迎来了密集的利好政策&#xff0c;近期&#xff0c;国家工信部又出台系列政策&#xff0c;实施工业制造企业数字化促进工程&#xff0c;推动工业制造企业更快更好地拥抱数字经济。…

数字安全设备制造有哪几种方式?

数字安全设备制造是指制造用于保护数字信息系统和网络安全的专用设备。以下是几种常见的数字安全设备制造方式&#xff1a; 集成式安全设备制造&#xff1a;集成式安全设备制造是将多种安全功能集成到单一的硬件设备或软件平台中。这种制造方式可以大大降低设备的成本和复杂性&…

vue3 + vite3 addRoute 实现权限管理系统

vue3 vite3 addRoute 实现权限控制 1、前言2、静态路由3、动态路由4、在组建中使用路由5、注意事项 1、前言 在权限系统开发中&#xff0c;根据后端返回的菜单列表动态添加路由是非常常见的需求&#xff0c;它可以实现根据用户权限动态加载可访问的页面。本篇文章我们将重点介…

第二届全国高校计算机技能竞赛——Java赛道

第二届全国高校计算机技能竞赛——Java赛道 小赛跳高 签到题 import java.util.*; public class Main{public static void main(String []args) {Scanner sc new Scanner(System.in);double n sc.nextDouble();for(int i 0; i < 4; i) {n n * 0.9;}System.out.printf(&…

探索公共厕所的数字化治理,智慧公厕完善公共厕所智能化的治理体系

随着城市化进程的不断发展&#xff0c;公共厕所治理成为一个不容忽视的问题。如何通过数字化手段来提升公共厕所管理水平&#xff0c;成为了一个备受关注的话题。本文将以智慧公厕领先厂家广州中期科技有限公司&#xff0c;大量精品案例项目实景实图&#xff0c;探讨公共厕所数…

品牌线上假货怎么治理

随着品牌的发展&#xff0c;母婴、家电、百货等行业&#xff0c;链接量暴增&#xff0c;销售店铺也较多&#xff0c;线上仅通过图片销售的形式&#xff0c;也导致了假货链接地滋生&#xff0c;假货分两种情况&#xff0c;一种是只销售假货的店铺&#xff0c;一种是真假混卖的店…

用numpy生成18种特殊数组

文章目录 单值数组特殊矩阵范德蒙德矩阵数值范围坐标网格绘图代码 所有创建数组的函数中&#xff0c;都有一个可选参数dtype&#xff0c;表示创建的数组的数据类型。 指定维度empty, eye, identity, ones, zeros, full模仿维度empty_like, ones_like, zeros_like, full_like特…

【Linux】C语言实现对文件的加密算法

异或加密 解密方式是进行第二次加密后自动解密 #define BUF_SIZE (16384) //16k /************************************************************** 功能描述: 加密实现 输入参数: --------------------------------------------------------------- 修改作者: 修改日期…

【小尘送书-第五期】《巧用ChatGPT快速提高职场晋升力》用ChatGPT快速提升职场能力,全面促进自身职业发展

大家好&#xff0c;我是小尘&#xff0c;欢迎你的关注&#xff01;大家可以一起交流学习&#xff01;欢迎大家在CSDN后台私信我&#xff01;一起讨论学习&#xff0c;讨论如何找到满意的工作&#xff01; &#x1f468;‍&#x1f4bb;博主主页&#xff1a;小尘要自信 &#x1…

qq录屏快捷键大全,玩转录制就这么简单(干货)

“qq有录屏快捷键吗&#xff1f;有点好奇&#xff0c;现在用qq录制屏幕&#xff0c;总是得去点击屏幕录制才可以出来&#xff0c;太麻烦了&#xff0c;如果可以通过快捷键的方式打开&#xff0c;会轻松许多&#xff0c;想问问大家&#xff0c;知道qq录屏快捷键是多少吗&#xf…

#你我都是国家队#,与泸州老窖一起为中国荣耀干杯

执笔 | 姜 姜 编辑 | 古利特 代表亚洲最高水平的体育盛会已经开幕两天&#xff0c;国家队运动员们在赛场上挥洒汗水&#xff0c;国人的激情也随之升温。 为迎接这场体育盛会&#xff0c;9月13日&#xff0c;TEAM CHINA中国国家队官方微博携手泸州老窖发布了一条态度短片&am…