Redis 常用数据类型插入性能对比:循环插入 vs. 批量插入

Redis 是一款高性能的键值数据库,其支持多种数据类型(String、Hash、List、Set、ZSet、Geo)。在开发中,经常会遇到需要插入大量数据的场景。如果逐条插入,性能会显得较低,而采用 Pipeline 批量插入 能大幅提升插入效率。本文将基于常见的 Redis 数据类型,对比循环插入与批量插入的性能差异。 以下测试结果仅供参考,真实环境请多测试! 


1. 测试环境说明

  • Redis 版本:3.x、5.x 或更高
  • Spring Boot 环境spring-boot-starter-data-redis

测试过程中,我们将模拟插入 1 万 / 10 万条数据,并记录执行时间。以下是常见的 Redis 数据类型及其插入方法。


2. 各数据类型的插入实现

2.1 String 类型
  • 循环插入:

逐条使用 opsForValue().set() 方法进行插入:

    /*** String类型测试循环插入性能* @param dataCount*/public void testInsertPerformanceStr(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForValue().set(StrKey+i, "value" + i);}log.info("使用String类型循环插入{}条数据,总耗时为: {} ms",dataCount, System.currentTimeMillis() - beginTime);}

  • 批量插入:

通过 Redis Pipeline 批量操作提升性能:

    /*** String类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedStr(int dataCount) {// 开始计时long startTime = System.currentTimeMillis();// 使用 Redis Pipeline 进行批量插入stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {for (int i = 0; i < dataCount; i++) {// 构造键值对String key = StrKey + i;String value = "value" + i;// 将命令加入 pipelineconnection.stringCommands().set(key.getBytes(), value.getBytes());}return null;});// 结束计时long elapsedTime = System.currentTimeMillis() - startTime;log.info("使用String类型批量插入{}条数据,总耗时为: {}ms", dataCount, elapsedTime);使用 Lua 脚本删除匹配的键//String luaScript = "local keys = redis.call('keys', ARGV[1]) " +//        "for i, key in ipairs(keys) do " +//        "redis.call('del', key) " +//        "end " +//        "return #keys";//DefaultRedisScript<Long> script = new DefaultRedisScript<>(luaScript, Long.class);//Long deletedKeysCount = redisTemplate.execute(script, Collections.emptyList(), StrKey + "*");////log.info("成功删除前缀为 {} 的所有键,共删除 {} 个键", StrKey, deletedKeysCount);}

性能对比
插入方式插入数据量耗时(ms)
循环插入1万条500+
批量插入1 万条150+

2.2 ZSet(有序集合)类型
  • 循环插入:
    /*** ZSet测试循环插入性能** @param dataCount*/public void testInsertPerformanceZSet(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForZSet().add(ZSetKey, "value" + i, i);}log.info("使用ZSet类型循环插入{}条数据,总耗时为: {} ms", dataCount, System.currentTimeMillis() - beginTime);}

  • 批量插入:

使用 opsForZSet().add() 的批量插入方法:

    /*** ZSet测试批量处理插入性能** @param dataCount*/public void testBatchInsertOptimizedZSet(int dataCount) {// 开始计时long startTime = System.currentTimeMillis();HashSet<ZSetOperations.TypedTuple<String>> redisBatchData = new HashSet<>();for (int i = 0; i < dataCount; i++) {redisBatchData.add(ZSetOperations.TypedTuple.of("value" + i, (double) i));}// 一次性批量插入stringRedisTemplate.opsForZSet().add(ZSetKey, redisBatchData);log.info("使用ZSet类型批量插入{}条数据,总耗时:{}ms ", dataCount, (System.currentTimeMillis() - startTime));}

性能对比
插入方式插入数据量耗时(ms)
循环插入1 万条660+
批量插入1 万条50+

2.3 Hash 类型
  • 循环插入:
    /*** Hash类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceHash(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForHash().put(HashKey, "key" + i, "value" + i);}log.info("使用Hash类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}
  • 批量插入:
    /*** Hash类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedHash(int dataCount) {long startTime = System.currentTimeMillis();// 构造批量数据Map<String, String> hashData = IntStream.range(0, dataCount).boxed().collect(Collectors.toMap(i -> "key" + i, i -> "value" + i));// 批量插入stringRedisTemplate.opsForHash().putAll(HashKey, hashData);log.info("使用Hash类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}

性能对比
插入方式插入数据量耗时(ms)
循环插入1 万条450+
批量插入1 万条15+

2.4 Set 类型
  • 循环插入:
    /*** Set类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceSet(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForSet().add("lps::test_set", "value" + i);}log.info("使用Set类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}
  • 批量插入:
    /*** Set类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedSet(int dataCount) {long startTime = System.currentTimeMillis();// 批量插入stringRedisTemplate.opsForSet().add("lps::test_set", Arrays.toString(IntStream.range(0, dataCount).mapToObj(i -> "value" + i).distinct().toArray()));log.info("使用Set类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}

性能对比
插入方式插入数据量耗时(ms)
循环插入1 万条430+
批量插入1 万条2+

2.5 Geo 类型
  • 循环插入:
    /*** Geo类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceGeo(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForGeo().add("lps::test_geo", generateValidPoint(i), "location" + i);}log.info("使用Geo类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}/*** 生成合法的 Geo 数据点*/private Point generateValidPoint(int index) {// 生成经度 [-180, 180]double longitude = (index % 360) - 180;// 生成纬度 [-85.05112878, 85.05112878]double latitude = ((index % 170) - 85) * 0.1;return new Point(longitude, latitude);}

  • 批量插入:
    /*** Geo类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedGeo(int dataCount) {long startTime = System.currentTimeMillis();// 构造批量数据List<RedisGeoCommands.GeoLocation<String>> geoLocations = IntStream.range(0, dataCount).mapToObj(i -> new RedisGeoCommands.GeoLocation<>("location" + i,generateValidPoint(i))).collect(Collectors.toList());// 批量插入stringRedisTemplate.opsForGeo().add("lps::test_geo", geoLocations);log.info("使用Geo类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}/*** 生成合法的 Geo 数据点*/private Point generateValidPoint(int index) {// 生成经度 [-180, 180]double longitude = (index % 360) - 180;// 生成纬度 [-85.05112878, 85.05112878]double latitude = ((index % 170) - 85) * 0.1;return new Point(longitude, latitude);}
性能对比
插入方式插入数据量耗时(ms)
循环插入1 万条496+
批量插入1 万条27+

 2.6 List 类型
  • 循环插入:
    /*** List类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceList(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForList().rightPush(ListKey, "value" + i);}log.info("使用List类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}

  • 批量插入:
    /*** List类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedList(int dataCount) {long startTime = System.currentTimeMillis();// 构造批量数据List<String> values = IntStream.range(0, dataCount).mapToObj(i -> "value" + i).collect(Collectors.toList());// 批量插入stringRedisTemplate.opsForList().rightPushAll(ListKey, values);log.info("使用List类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}
性能对比
插入方式插入数据量耗时(ms)
循环插入1 万条429+
批量插入1 万条8+

3. 执行图片

5.0.14.1版本 - 1w数据插入

5.0.14.1版本 - 10w数据插入

3.2.100版本 - 1w数据插入

3.2.100版本 - 10w数据插入

4. 完整类如下


@Service
@Slf4j
public class RedisServiceImpl implements RedisService {@Resourceprivate StringRedisTemplate stringRedisTemplate;public static final String ZSetKey = "lps::test_zset";public static final String StrKey = "lps::test_str::";public static final String ListKey = "lps::test_list";public static final String HashKey = "lps::test_hash";@Overridepublic void runInsert(int number) {checkVersion();//ZSet类型testInsertPerformanceZSet(number);testBatchInsertOptimizedZSet(number);//String类型testInsertPerformanceStr(number);testBatchInsertOptimizedStr(number);//List类型testInsertPerformanceList(number);testBatchInsertOptimizedList(number);//Hash类型testInsertPerformanceHash(number);testBatchInsertOptimizedHash(number);//Set类型testInsertPerformanceSet(number);testBatchInsertOptimizedSet(number);//Geo类型testInsertPerformanceGeo(number);testBatchInsertOptimizedGeo(number);}public void checkVersion() {RedisConnection connection = Objects.requireNonNull(stringRedisTemplate.getConnectionFactory()).getConnection();String redisVersion = String.valueOf(Objects.requireNonNull(connection.info("server")).get("redis_version"));log.info("本台机器的Redis 版本为:{}", redisVersion);}/*** ZSet测试循环插入性能** @param dataCount*/public void testInsertPerformanceZSet(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForZSet().add(ZSetKey, "value" + i, i);}log.info("使用ZSet类型循环插入{}条数据,总耗时为: {} ms", dataCount, System.currentTimeMillis() - beginTime);}/*** ZSet测试批量处理插入性能** @param dataCount*/public void testBatchInsertOptimizedZSet(int dataCount) {// 开始计时long startTime = System.currentTimeMillis();HashSet<ZSetOperations.TypedTuple<String>> redisBatchData = new HashSet<>();for (int i = 0; i < dataCount; i++) {redisBatchData.add(ZSetOperations.TypedTuple.of("value" + i, (double) i));}// 一次性批量插入stringRedisTemplate.opsForZSet().add(ZSetKey, redisBatchData);log.info("使用ZSet类型批量插入{}条数据,总耗时:{}ms ", dataCount, (System.currentTimeMillis() - startTime));}/*** String类型测试循环插入性能** @param dataCount*/public void testInsertPerformanceStr(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForValue().set(StrKey + i, "value" + i);}log.info("使用String类型循环插入{}条数据,总耗时为: {} ms", dataCount, System.currentTimeMillis() - beginTime);}/*** String类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedStr(int dataCount) {// 开始计时long startTime = System.currentTimeMillis();// 使用 Redis Pipeline 进行批量插入stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {for (int i = 0; i < dataCount; i++) {// 构造键值对String key = StrKey + i;String value = "value" + i;// 将命令加入 pipelineconnection.stringCommands().set(key.getBytes(), value.getBytes());}return null;});// 结束计时long elapsedTime = System.currentTimeMillis() - startTime;log.info("使用String类型批量插入{}条数据,总耗时为: {}ms", dataCount, elapsedTime);使用 Lua 脚本删除匹配的键//String luaScript = "local keys = redis.call('keys', ARGV[1]) " +//        "for i, key in ipairs(keys) do " +//        "redis.call('del', key) " +//        "end " +//        "return #keys";//DefaultRedisScript<Long> script = new DefaultRedisScript<>(luaScript, Long.class);//Long deletedKeysCount = redisTemplate.execute(script, Collections.emptyList(), StrKey + "*");////log.info("成功删除前缀为 {} 的所有键,共删除 {} 个键", StrKey, deletedKeysCount);}/*** List类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceList(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForList().rightPush(ListKey, "value" + i);}log.info("使用List类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}/*** List类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedList(int dataCount) {long startTime = System.currentTimeMillis();// 构造批量数据List<String> values = IntStream.range(0, dataCount).mapToObj(i -> "value" + i).collect(Collectors.toList());// 批量插入stringRedisTemplate.opsForList().rightPushAll(ListKey, values);log.info("使用List类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}/*** Hash类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceHash(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForHash().put(HashKey, "key" + i, "value" + i);}log.info("使用Hash类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}/*** Hash类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedHash(int dataCount) {long startTime = System.currentTimeMillis();// 构造批量数据Map<String, String> hashData = IntStream.range(0, dataCount).boxed().collect(Collectors.toMap(i -> "key" + i, i -> "value" + i));// 批量插入stringRedisTemplate.opsForHash().putAll(HashKey, hashData);log.info("使用Hash类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}/*** Set类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceSet(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForSet().add("lps::test_set", "value" + i);}log.info("使用Set类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}/*** Set类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedSet(int dataCount) {long startTime = System.currentTimeMillis();// 批量插入stringRedisTemplate.opsForSet().add("lps::test_set", Arrays.toString(IntStream.range(0, dataCount).mapToObj(i -> "value" + i).distinct().toArray()));log.info("使用Set类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}/*** Geo类型测试循环插入性能** @param dataCount 插入的数据总量*/public void testInsertPerformanceGeo(int dataCount) {long beginTime = System.currentTimeMillis();for (int i = 0; i < dataCount; i++) {stringRedisTemplate.opsForGeo().add("lps::test_geo", generateValidPoint(i), "location" + i);}log.info("使用Geo类型循环插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - beginTime);}/*** Geo类型测试批量处理插入性能** @param dataCount 插入的数据总量*/public void testBatchInsertOptimizedGeo(int dataCount) {long startTime = System.currentTimeMillis();// 构造批量数据List<RedisGeoCommands.GeoLocation<String>> geoLocations = IntStream.range(0, dataCount).mapToObj(i -> new RedisGeoCommands.GeoLocation<>("location" + i,generateValidPoint(i))).collect(Collectors.toList());// 批量插入stringRedisTemplate.opsForGeo().add("lps::test_geo", geoLocations);log.info("使用Geo类型批量插入{}条数据,总耗时为: {}ms", dataCount, System.currentTimeMillis() - startTime);}/*** 生成合法的 Geo 数据点*/private Point generateValidPoint(int index) {// 生成经度 [-180, 180]double longitude = (index % 360) - 180;// 生成纬度 [-85.05112878, 85.05112878]double latitude = ((index % 170) - 85) * 0.1;return new Point(longitude, latitude);}
}

5. 总结与优化建议

  • 批量插入性能远远高于循环插入,尤其是在数据量较大时,差距更为明显。
  • 使用 Redis Pipeline 或批量操作接口是提高 Redis 性能的有效方法。
  • 在批量操作时,尽量将数据准备在内存中再一次性提交到 Redis,减少网络开销。
  • Geo 类型插入需注意经纬度合法范围,避免报错。

通过这些优化方法,Redis 的插入性能可以得到显著提升,在高并发场景下尤为重要。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源动态表单form-create-designer 扩展个性化配置的最佳实践教程

在开源低代码表单设计器 form-create-designer 的右侧配置面板里&#xff0c;field 映射规则为开发者提供了强大的工具去自定义和增强组件及表单配置的显示方式。通过这些规则&#xff0c;你可以简单而高效地调整配置项的展示&#xff0c;提升用户体验。 源码地址: Github | G…

Java语言编程,通过阿里云mongo数据库监控实现数据库的连接池优化

一、背景 线上程序连接mongos超时&#xff0c;mongo监控显示连接数已使用100%。 java程序报错信息&#xff1a; org.mongodb.driver.connection: Closed connection [connectionId{localValue:1480}] to 192.168.10.16:3717 because there was a socket exception raised by…

深入浅出分布式缓存:原理与应用

文章目录 概述缓存分片算法1. Hash算法2. 一致性Hash算法3. 应用场景Redis集群方案1. Redis 集群方案原理2. Redis 集群方案的优势3. Java 代码示例:Redis 集群数据定位Redis 集群中的节点通信机制:Gossip 协议Redis 集群的节点通信:Gossip 协议Redis 集群的节点通信流程Red…

Loom篇之java虚拟线程那些事儿

我们在之前的文章中提到了java推出纤程的背景和原因。在近三十年来&#xff0c;Java 开发人员一直依赖线程作为并发服务器应用程序的构建块。每个方法中的每个语句都在线程内执行&#xff0c;并且由于 Java 是多线程的&#xff0c;因此多个执行线程会同时发生。线程是 Java 的并…

自然语言处理: RAG优化之Embedding模型选型重要依据:mteb/leaderboard榜

本人项目地址大全&#xff1a;Victor94-king/NLP__ManVictor: CSDN of ManVictor git地址&#xff1a;https://github.com/opendatalab/MinerU 写在前面: 笔者更新不易&#xff0c;希望走过路过点个关注和赞&#xff0c;笔芯!!! 写在前面: 笔者更新不易&#xff0c;希望走过路…

如何选择服务器

如何选择服务器 选择服务器时应考虑以下几个关键因素&#xff1a; 性能需求。根据网站的预期流量和负载情况&#xff0c;选择合适的处理器、内存和存储容量。考虑网站是否需要处理大量动态内容或高分辨率媒体文件。 可扩展性。选择一个可以轻松扩展的服务器架构&#xff0c;以便…

Spring 框架七大模块(Java EE 学习笔记03)

​ ​核心容器模块&#xff08;Core Container&#xff09; 核心容器模块在Spring的功能体系中起着支撑性作用&#xff0c;是其他模块的基石。核心容器层主要由Beans模块、Core模块、Contex模块和SpEL模块组成。 &#xff08;1&#xff09;Beans模块。它提供了BeanFactory类&…

2025-2026财年美国CISA国际战略规划(下)

文章目录 前言四、加强综合网络防御&#xff08;一&#xff09;与合作伙伴共同实施网络防御&#xff0c;降低集体风险推动措施有效性衡量 &#xff08;二&#xff09;大规模推动标准和安全&#xff0c;以提高网络安全推动措施有效性衡量 &#xff08;三&#xff09;提高主要合作…

【大数据技术与开发实训】携程景点在线评论分析

景点在线评论分析 题目要求实验目标技术实现数据采集获取所有相关景点页面的 URL获取所有相关景点对应的 poiId 及其他有用信息通过 poiId 获取所有景点的全部评论数据采集结果 数据预处理景点信息的数据预处理查看数据基本信息缺失值处理 用户评论的数据处理缺失值处理分词、去…

《第十部分》1.STM32之通信接口《精讲》之IIC通信---介绍

经过近一周的USART学习&#xff0c;我深刻体会到通信对单片机的重要性。它就像人类的手脚和大脑&#xff0c;只有掌握了通信技术&#xff0c;单片机才能与外界交互&#xff0c;展现出丰富多彩的功能&#xff0c;变得更加强大和实用。 单片机最基础的“语言”是二进制。可惜&am…

ES 基本使用与二次封装

概述 基本了解 Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;基于 Apache Lucene 构建。它提供了对海量数据的快速全文搜索、结构化搜索和分析功能&#xff0c;是目前流行的大数据处理工具之一。主要特点即高效搜索、分布式存储、拓展性强 核心功能 全文搜索:…

单片机_简单AI模型训练与部署__从0到0.9

IDE&#xff1a; CLion MCU&#xff1a; STM32F407VET6 一、导向 以求知为导向&#xff0c;从问题到寻求问题解决的方法&#xff0c;以兴趣驱动学习。 虽从0&#xff0c;但不到1&#xff0c;剩下的那一小步将由你迈出。本篇主要目的是体验完整的一次简单AI模型部署流程&#x…

Python3 爬虫 Scrapy的安装

Scrapy是基于Python的分布式爬虫框架。使用它可以非常方便地实现分布式爬虫。Scrapy高度灵活&#xff0c;能够实现功能的自由拓展&#xff0c;让爬虫可以应对各种网站情况。同时&#xff0c;Scrapy封装了爬虫的很多实现细节&#xff0c;所以可以让开发者把更多的精力放在数据的…

golang实现TCP服务器与客户端的断线自动重连功能

1.服务端 2.客户端 生成服务端口程序: 生成客户端程序: 测试断线重连: 初始连接成功

【Spring Boot】# 使用@Scheduled注解无法执行定时任务

1. 前言 在 Spring Boot中&#xff0c;使用Scheduled注解来定义定时任务时&#xff0c;定时任务不执行&#xff1b;或未在规定时间执行。 import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component;Component public c…

java 老矣,尚能饭否?

随笔 从千万粉丝“何同学”抄袭开源项目说起&#xff0c;为何纯技术死路一条&#xff1f; 数据源的统一与拆分 监控报警系统的指标、规则与执行闭环 java 老矣&#xff0c;尚能饭否&#xff1f; 一骑红尘妃子笑&#xff0c;无人知是荔枝来! java 老吗&#xff1f; 去年看…

[译]Elasticsearch Sequence ID实现思路及用途

原文地址:https://www.elastic.co/blog/elasticsearch-sequence-ids-6-0 如果 几年前&#xff0c;在Elastic&#xff0c;我们问自己一个"如果"问题&#xff0c;我们知道这将带来有趣的见解&#xff1a; "如果我们在Elasticsearch中对索引操作进行全面排序会怎样…

解锁PPTist的全新体验:Windows系统环境下本地部署与远程访问

文章目录 前言1. 本地安装PPTist2. PPTist 使用介绍3. 安装Cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 前言 在Windows系统环境中&#xff0c;如何本地部署开源在线演示文稿应用PPTist&#xff0c;并实现远程访问&#xff1f;本文将为您提供详细的部署和配置指南。 P…

一文学会Golang里拼接字符串的6种方式(性能对比)

g o l a n g golang golang的 s t r i n g string string类型是不可修改的&#xff0c;对于拼接字符串来说&#xff0c;本质上还是创建一个新的对象将数据放进去。主要有以下几种拼接方式 拼接方式介绍 1.使用 s t r i n g string string自带的运算符 ans ans s2. 使用…

IEC61850读服务器目录命令——GetServerDirectory介绍

IEC61850标准中的GetServerDirectory命令是变电站自动化系统中非常重要的一个功能&#xff0c;它主要用于读取服务器的目录信息&#xff0c;特别是服务器的逻辑设备节点&#xff08;LDevice&#xff09;信息。以下是对GetServerDirectory命令的详细介绍。 目录 一、命令功能 …