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

低延时+高并发+强事务丨DolphinDB 交易型内存存储引擎 IMOLTP 使用指南

1. 背景

在一些数据库应用场景中,例如金融行业的交易系统,其主要工作负载来源于对关系表的高频度、高并发的更新和查询操作。这样的应用场景要求数据的读写和计算能够具有低延迟、高并发的特征,同时保证极高的数据一致性,并提供 ACID 事务的支持,是典型的在线事务处理(OLTP)场景

传统的存储引擎由于其架构的设计出发点是将数据存储在磁盘上,在面对上述场景要求时,软硬件层面面临巨大挑战,无法很好地满足上述苛刻的性能要求。而在这些场景中,往往需要维护的数据量实际上没有那么大,那么,能否把所有的数据都维护在内存里呢?这样就可以减少读写磁盘的带宽,能够大大降低数据库的延迟和提升数据库的并发度。

基于这个想法,DolphinDB 设计并实现了一款纯自研的内存 OLTP 数据库,它有以下特点

  • 将所有数据都存储在内存中,省去磁盘 I/O 的开销;
  • 以行存的形式来组织数据,主要适用于 OLTP 的场景;
  • 支持创建 B+ 树索引 (主键索引和二级索引) 来应对高频度、高并发的更新和查询操作;
  • 支持事务,默认为 snapshot isolation;
  • 实现 Write-Ahead-Logging 和 checkpoint 机制以保证数据的持久化和恢复;
  • 为加速重启时的恢复过程,实现了并行恢复机制。

下文将介绍 OLTP 的使用方式。

需要在配置文件里加上  enableIMOLTPEngine=true 来开启 OLTP 引擎。

2. DDL

2.1 建库

使用 database 函数来创建 OLTP 数据库,语法与创建 OLAP/TSDB 数据库一样,但是有以下注意事项:

  • directory 必须以 oltp:// 开头。
  • engine 必须为 IMOLTP
  • OLTP 目前只支持单机版本,分区方式可以任意填写。
dbName = "oltp://test_imoltp"
db = database(dbName, VALUE, 1..100, , "IMOLTP")

2.2 建表

使用 createIMOLTPTable 函数来创建 OLTP 表,语法如下:

createIMOLTPTable(dbHandle, table, tableName, primaryKey, [secondaryKey], [uniqueFlag])

primaryKey 用来指定主键索引的键。主键索引有且只有一个,每个 OLTP 表都必须指定。主键索引是 unique 的,插入数据时会检查是否满足唯一性约束(即不能插入重复元素),若违反则报错。主键可以包含多个字段(字段即为列名)。

secondaryKey 用来指定二级索引的键。二级索引可选,并且每个 OLTP 表可以创建多个二级索引。二级索引有 unique 和 non-unique 两种,两者的区别在于 unique 索引需要满足唯一性约束,而 non-unique 索引没有这个限制。由 uniqueFlag 来指定二级索引是否是 unique 的。二级索引的键同样可以包含多个字段。

// pt1 以 id 为主键,没有二级索引
pt1 = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),"test_table_1",primaryKey=`id
)// pt2 以 id,sym 为主键,有一个 unique 二级索引:以 val2,sym 为键
pt2 = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),"test_table_2",primaryKey=`id`sym,secondaryKey=`val2`sym,uniqueFlag=true
)// pt3 以 id 为主键,有一个非 unique 二级索引:以 val1 为键;一个 unique 二级索引:以 sym 为键
pt3 = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),"test_table_3",primaryKey=`id,secondaryKey=[`val1, `sym],uniqueFlag=[false, true]
)

通常来说,对于查询效率:主键索引优于二级索引优于非索引,如果查询时不能利用任何索引,则只能进行全表扫描。合理地创建二级索引可以提升查询的效率,但是相应地会降低写入的效率,因为写入时 (insert/delete/update) 需要修改相应的索引。

2.3 删库/删表

使用 dropTable 和 dropDatabase 来删表删库,使用方式与 OLAP/TSDB 没有区别。

db.dropTable("test_table_1")if (existsDatabase(dbName)) {dropDatabase(dbName)
}

3. DML

后文的例子假设已经执行过下面的脚本来建库建表:

dbName = "oltp://test_imoltp"
tableName = "test_table"if (existsDatabase(dbName)) {dropDatabase(dbName)
}db = database(dbName, VALUE, 1..100, , "IMOLTP")// pt 以 id 为主键,没有二级索引
pt = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),tableName,primaryKey=`id
)

3.1 写入数据

写入数据可以用 append! 和 insert into,使用方式与 OLAP/TSDB 一样。

pt = loadTable("oltp://test_imoltp", "test_table")id = 1..100
val1 = id * 10
val2 = rand(10000, size(id))
sym = take(`aaa`bbb`ccc`ddd`eee, size(id))
pt.append!(table(id, val1, val2, sym))insert into pt values(200, 2000, 1111, `xxx)
insert into pt values(201, 2010, 2222, `yyy)
insert into pt values(211..220, (211..220)*10, take(9527, 10), take(`xxx`yyy`zzz, 10))insert into pt(id, sym) values(1000, `aaa)
insert into pt(id, sym, val1) values(1001, `bbb, 10010)

3.2 查询数据

使用 SQL 来查询数据。where 条件非常重要,如果一次查询无法利用索引,那么性能会大幅降低。

pt = loadTable("oltp://test_imoltp", "test_table")select * from pt where id = 10  // 点查,用主键索引
select * from pt where id > 100, id < 200  // 范围查询,用主键索引select * from pt where val1 = 1000  // 全表扫描,无法利用索引

3.3 更新数据

使用 SQL 来更新数据。

pt = loadTable("oltp://test_imoltp", "test_table")update pt set val1 = 100 where id = 1
update pt set val1 = id + val1 where id < 10

3.4 删除数据

使用 SQL 来删除数据。

pt = loadTable("oltp://test_imoltp", "test_table")delete from pt where id = 1
delete from pt where id >= 100, id <= 110

4. 事务

使用 transaction 语句块可以在一个事务内执行多条 DML 语句,在一个事务范围内,所有的 DML 操作都会一起成功或一起失败。若一个事务执行的时候有异常抛出,会自动撤销本次事务的所有更改。

pt = loadTable("oltp://test_imoltp", "test_table")delete from pttransaction {insert into pt values(0, 0, 0, `aaa)insert into pt values(1, 1, 1, `bbb)insert into pt values(2, 2, 2, `ccc)commit  // 提交事务(可以省略)
}
assert (exec id from pt order by id) == [0,1,2]transaction {insert into pt values(3, 3, 3, `ddd)insert into pt values(4, 4, 4, `eee)delete from pt where id = 1update pt set id = 10 where id = 0assert (exec id from pt order by id) == [2,3,4,10]rollback  // 强制回滚事务,撤销所有修改
}
assert (exec id from pt order by id) == [0,1,2]

commit 表示提交本次事务的所有更改,rollback 表示撤销本次事务的所有更改。不需要显式地写 commit,出了 transaction 语句块的作用域时会自动 commit。

若不显式地使用  transaction 语句块,则每一句 SQL 都是一个事务。

注意:DDL 语句(即建表,删表等)不能放在  transaction 语句块里面,因为 DDL 目前不支持事务。

5. 配置参数

目前 OLTP 有以下配置参数可以设置:

  • enableIMOLTPEngine,bool 类型。表示是否开启 OLTP 引擎。默认为 false。
  • enableIMOLTPRedo,bool 类型。表示是否开启 WAL(Write-Ahead-Log),开启之后才能保证数据不会丢失。默认为 true。
  • IMOLTPRedoFilePath,string 类型。表示 redo 文件(即 WAL 文件)的路径(注意不是目录),可以为绝对路径或者相对路径。当为相对路径时,相对于 home 目录下的 IMOLTP 目录。默认为 home 目录下的 IMOLTP/im_oltp.redo
  • IMOLTPSyncOnTxnCommit,bool 类型。只在 enableIMOLTPRedo 为 true 时(即开启了 WAL)有意义。默认为 false。详细解释见下文。
  • enableIMOLTPCheckpoint,bool 类型。表示是否开启 checkpoint。默认为 true。
  • IMOLTPCheckpointFilePath,string 类型。表示 checkpoint 文件的路径(注意不是目录),可以为绝对路径或者相对路径。当为相对路径时,相对于 home 目录下的 IMOLTP 目录。默认为 home 目录下的 IMOLTP/im_oltp.ckp
  • IMOLTPCheckpointThreshold,long 类型,单位为 MiB。 表示:如果 redo 文件里面的 log 大小达到该阈值后,会触发一次 checkpoint。默认为 100 MiB。
  • IMOLTPCheckpointInterval,long 类型,单位为秒。表示每隔 # 秒之后强制做一次 checkpoint。默认为 60 秒。

关于 IMOLTPSyncOnTxnCommit 的含义:

在开启 WAL 后,事务对数据进行修改之前,会先写日志到持久化存储。系统重启时会回放 redo 文件里的日志,恢复到重启之前的状态。

如果 IMOLTPSyncOnTxnCommit 为 false,事务 commit 成功之后,保证日志写到了操作系统的缓存里,但是不保证日志已经写到了持久化存储上。因此,如果进程崩溃, 数据不会丢失, 但是当操作系统崩溃(机器掉电), 可能会有数据丢失。

如果 IMOLTPSyncOnTxnCommit 为 true,在事务 commit 成功之后,保证日志已经写到了持久化存储上,即使操作系统崩溃,数据也不会丢失。(但是如果存储设备故障, 还是可能有数据丢失)。

如果需要持久化数据,并且对数据的一致性要求较高,绝对无法忍受数据丢失,推荐把 enableIMOLTPRedo 和 IMOLTPSyncOnTxnCommit 都设置为 true。这种模式下,(写入)性能较差。

如果需要持久化数据,并且可以容忍操作系统崩溃(比如机器掉电等小概率事件)导致的数据丢失,推荐把 enableIMOLTPRedo 设置为 true, 把 IMOLTPSyncOnTxnCommit 设置为 false。这种模式下,(写入)性能较好。默认为这种配置。

6. 内置函数 triggerCheckpointForIMOLTP

当开启了 checkpoint 时(即 enableIMOLTPCheckpoint 配置为 true ),系统会在达到以下两个条件之一时自动触发 checkpoint:

  • redo 文件里面的 log 大小达到阈值(IMOLTPCheckpointThreshold MiB);
  • 或者,距离上一次 checkpoint 过去了 IMOLTPCheckpointInterval 秒。

用户也可以手动调用 triggerCheckpointForIMOLTP 函数来触发 checkpoint。函数语法如下:

triggerCheckpointForIMOLTP([force=false], [sync=false])

参数:

  • force,bool 类型,可选。表示是否强制做 checkpoint。如果为 false,并且当前并没有达到做 checkpoint 的条件(即 redo 文件里的 log 大小没有达到 IMOLTPCheckpointThreshold),则忽略这次请求。默认为 false。
  • sync,bool 类型,可选。表示是否异步。如果为 false,则该函数请求一次异步的 checkpoint,并不会等到请求完成再返回;否则该函数会等到请求完成(注意不一定做了 checkpoint)再返回。默认为 false。

7. 总结

DolphinDB 推出的 OLTP 内存数据库适用于高并发、低延迟的在线事务处理场景。该数据库将数据存储在内存中,支持 B+ 树索引、事务、Write-Ahead-Logging 和 checkpoint 机制。事务通过 transaction 语句块实现,保证了操作的原子性。用户还可以通过配置参数的配置以及内置函数 triggerCheckpointForIMOLTP 的使用,手动触发 checkpoint。

总体而言,DolphinDB 的 OLTP 引擎适用于对数据一致性和性能要求较高的场景。

相关文章:

低延时+高并发+强事务丨DolphinDB 交易型内存存储引擎 IMOLTP 使用指南

1. 背景 在一些数据库应用场景中&#xff0c;例如金融行业的交易系统&#xff0c;其主要工作负载来源于对关系表的高频度、高并发的更新和查询操作。这样的应用场景要求数据的读写和计算能够具有低延迟、高并发的特征&#xff0c;同时保证极高的数据一致性&#xff0c;并提供 …...

写代码的修养

看山是山&#xff0c;看水是水 此境界 对业务的思考是浅层的&#xff0c;代码写的不通用&#xff0c;扩展性差&#xff0c;表现在无设计模式 看山不是山&#xff0c;看水不是水 此境界 对业务的思考是中层的&#xff0c;代码写的通用&#xff0c;扩展性好&#xff0c;表现为…...

springboot 问题整合

springboot 启动后访问报错 问题&#xff1a;org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 原因&#xff1a;mybatis 的全局配置文件和 sql 映射文件没有写 解决&#xff1a;在 application.yml 中添加 mybatis 配置 mybatis:# 全局配…...

UNIAPP二维码展示页亮度调至最亮返回恢复进入前亮度

onLoad(params) {let num plus.screen.getBrightness().toString(); //转字符串是要存到stoage中number类型会存储失败plus.storage.setItem("pmld", num)plus.screen.setBrightness(1); //设置屏幕亮度&#xff0c;范围0-1 }onUnload() {let platformuni.getSystem…...

Golang ProtoBuf 初学者完整教程:安装

一、Protobuf 特点 更高效&#xff1a;使用二进制编码&#xff0c;相比XML/JSON更加高效 跨语言支持&#xff1a;Protobuf 在 .proto 定义需要处理的结构化数据&#xff0c;可以通过 protoc 工具&#xff0c;将 .proto 文件转换为 C、C、Golang、Java、Python 等多种语言的代…...

Isolation Forest 简介

1. 简介 孤立森林 iForest(Isolation Forest)是一种无监督学习算法&#xff0c;用于识别异常值。其基本原理是&#xff1a;异常数据由于数量较少且与正常数据差异较大&#xff0c;因此在被隔离时需要较少的步骤。 两个假设&#xff1a; 1. 异常的值是非常少的(如果异常值很多&…...

Java爬虫携带sign签名

站点&#xff1a;https://www.mytokencap.com/ 代码分析先不写了&#xff0c;大家自行解决&#xff0c;贴代码 1、业务请求设计 public static void md5Pro() {String url "https://api.mytokenapi.com/ticker/currencylistforall";Map<String, String> he…...

设计者模式之中介者模式(下)

3&#xff09;中介者与同事类的扩展 1.结构图 新增了具体同事类Label和具体中介者类SubConcreteMediator。 2.代码实现 //文本标签类&#xff1a;具体同事类 public class Label extends Component {public void update() {System.out.println("文本标签内容改变&#…...

SAP SD学习笔记04 - 出荷Plant(交货工厂),出荷Point(装运点),输送计划,品目的可用性检查,一括纳入/分割纳入,仓库管理

上一章讲了SD的主数据。 SAP SD学习笔记03 - SD模块中的主数据-CSDN博客 本章讲出荷Plant&#xff08;交货工厂&#xff09;&#xff0c;出荷Point&#xff08;装运点&#xff09;和出和路线。 还是偏理论多一些&#xff0c;后面的文章尽量多加些练习巩固一下。 1&#xff0…...

bind包装器——C++新特性(三)

文章目录 bindbind函数模板的原型bind 包装器的用途其他使用示例 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alaskan Malamute &#x1f4dc; 博主的代码仓库主页 [ Gitee ]&#xff1a;ryanala [GitHub]&#xff1a; Ryan-Ala bind bind也是一种函数包装器&#xf…...

MXNet的下载安装及问题处理

1、MXNet介绍&#xff1a; MXNet是一个开源的深度学习框架&#xff0c;以其灵活性和效率著称&#xff0c;支持多种编程接口&#xff0c;包括Python、C、R、Julia、Scala等。MXNet支持大规模分布式训练&#xff0c;同时兼顾CPU和GPU的计算资源&#xff0c;尤其擅长于模型并行和数…...

Python 中的列表排序和排序规则

Python 中的列表排序和排序规则 在 Python 中&#xff0c;列表的排序是一个常见的操作&#xff0c;可以使用内置函数 sorted() 或列表对象的 sort() 方法来完成。下面将介绍这两种方法以及排序规则的使用方式。 1. 使用 sorted() 函数排序列表&#xff08;临时性排序&#xf…...

面经整理1

感觉好几个都是backtracking Letter Combinations of a Phone Number - LeetCode 典型的backtracking&#xff0c;注意String的处理 class Solution {String[] keyboard new String[]{"", "", "abc","def","ghi","…...

ChatGPT个人专用版 SSRF漏洞复现(CVE-2024-27564)

0x01 产品简介 ChatGPT个人专用版是一种基于 OpenAI 的 GPT-3.5 、GPT-4.0语言模型的产品。它是设计用于 Web 环境中的聊天机器人,旨在为用户提供自然语言交互和智能对话的能力。PHP版调用OpenAI接口进行问答和画图,采用Stream流模式通信,一边生成一边输出。前端采用EventS…...

Python中的可哈希与不可哈希对象详解

文章目录 1. 前置知识&#xff1a;哈希是什么2. 可哈希和不可哈希对象的定义2.1可哈希2.2 不可哈希 3. 对象的哈希方法3.1 自定义对象的哈希方法3.2 可哈希性与等价性3.3 哈希值的用途 推荐 在复习可变对象和不可变对象时&#xff0c;学到了这个内容 1. 前置知识&#xff1a;哈…...

【嵌入式DIY实例】-DIY速度计

DIY速度计 文章目录 DIY速度计1、硬件准备1.1 NEO-6M GPS模块介绍1.2 硬件接线原理图2、代码实现本文将介绍如何使用模拟仪表和 GPS 模块制作 DIY Arduino 速度计。 仪表用于显示当前速度,而GPS模块用于实时跟踪速度。 该项目将 Arduino 板与 GPS 模块相结合,在经典模拟仪表上…...

1.0 Hadoop 教程

1.0 Hadoop 教程 分类 Hadoop 教程 Hadoop 是一个开源的分布式计算和存储框架&#xff0c;由 Apache 基金会开发和维护。 Hadoop 为庞大的计算机集群提供可靠的、可伸缩的应用层计算和存储支持&#xff0c;它允许使用简单的编程模型跨计算机群集分布式处理大型数据集&#xf…...

【无人机/平衡车/机器人】详解STM32+MPU6050姿态解算—卡尔曼滤波+四元数法+互补滤波(文末附3个算法源码)

效果: MPU6050姿态解算-卡尔曼滤波+四元数+互补滤波 目录 基础知识详解 欧拉角...

智能水务系统:构建高效节水的城市水网

随着城市化进程的加速和人民生活水平的提高&#xff0c;对水务管理的需求也越来越高。传统的水务管理方式已经无法满足现代社会的需求&#xff0c;而智能水务系统的出现为水务管理带来了新的变革。本文将从项目背景、需求分析、建设目标、建设内容、技术方案、安全设计等方面&a…...

【JavaEE初阶系列】——网络编程 UDP客户端/服务器 程序实现

目录 &#x1f6a9;UDP和TCP之间的区别 &#x1f388;TCP是有连接的 UDP是无连接的 &#x1f388;TCP是可靠传输 UDP是不可靠传输 &#x1f388;TCP是面向字节流 UDP是面向数据报 &#x1f388;TCP和UDP是全双工 &#x1f469;&#x1f3fb;‍&#x1f4bb;UDP的socket ap…...

数据结构复习指导之绪论(算法的概念以及效率的度量)

文章目录 绪论&#xff1a; 2.算法和算法评价 知识总览 2.1算法的基本概念 知识点回顾与重要考点 2.2算法效率的度量 知识总览 1.时间复杂度 2.空间复杂度 知识点回顾与重要考点 归纳总结 绪论&#xff1a; 2.算法和算法评价 知识总览 2.1算法的基本概念 算法( Al…...

C语言经典例题(23)

1.求n的阶乘。(不考虑溢出) #include <stdio.h>int fac(int n);int main() {int n 0;scanf("%d", &n);int sum fac(n);printf("%d", sum);return 0; }int fac(int n) {if (n > 1){return n * fac(n - 1);}elsereturn 1; }2.求第n个斐波那契…...

Gitea的简单介绍

Gitea 是一个自由、开源、轻量级的 Git 服务程序。它是为了建立一个易于使用的、类似 GitHub 的 Git 服务而创建的。Gitea 采用 Go 语言编写,具有简单、快速、易于安装和配置的特点。 Gitea 提供了一个基本的 Web 界面,可以方便地进行代码托管、问题跟踪、协作等操作。用户可…...

Qt信号与槽

我们在使用Qt的时候&#xff0c;不使用Qt Designer 的方式进行开发&#xff0c;使用ui文件&#xff0c;信号与槽的连接方式是生成代码之后才能在setupUi函数里才能看到&#xff0c;或者需要进入Ui设计器里的信号槽模式里才能看到信号槽的连接。所以我们最好使用代码绘制界面。 …...

QQ农场-phpYeFarm添加数据教程

前置知识 plugin\qqfarm\core\data D:\study-project\testweb\upload\source\plugin\qqfarm\core\data 也就是plugin\qqfarm\core\data是一个缓存文件,如果更新农场数据后,必须要删除才可以 解决种子限制(必须要做才可以添加成功) 你不更改加入了id大于2000直接删除种子 D…...

Java中创建多线程的方法

继承Thread类&#xff0c;对该类进行new一个实例&#xff0c;对实例调用start方法&#xff0c;重写run方法。 缺点&#xff1a;单继承&#xff0c;无法继承 public class myThread extends Thread {public static void main(String[] args) {myThread myThread new myThread()…...

MT3020 任务分配

思路&#xff1a;利用二分找到某个时间是满足“k个人可以完成” &#xff0c;并且时间最小。 因为尽量让后面的人做任务&#xff0c;所以从后往前排任务&#xff08;倒着分配&#xff09;。从后往前遍历任务&#xff0c;如果此人加上这个任务超出之前求得的时间&#xff0c;就…...

【Redis】事务

Redis事务是一组命令的集合。这组命令顺序化执行而不会被其他命令插入。 Redis事务命令 命令描述DISCARD取消事务&#xff0c;放弃执行EXEC执行事务MULTI标记事务的开始UNWATCH取消WATCH对所有key的监控WATCH监控所有key Redis事务特点 特点说明单独的隔离操作Redis命令执行…...

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…...

内网通如何去除广告,内网通免广告生成器

公司使用内网通内部传输确实方便&#xff01;但是会有广告弹窗推送&#xff01;这个很烦恼&#xff01;那么如何去除广告呢&#xff01; 下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1CVVdWexliF3tBaFgN1W9aw?pwdhk7m 提取码&#xff1a;hk7m ID&#xff1a;…...

食品品牌推广方案/广东网站se0优化公司

IBM全球服务中心最近发布的一份白皮书描述了IBM技术研究院&#xff08;Academy of Technology&#xff09;为取得SOA实施的成功所运用的经验。具体地讲&#xff0c;他们关注于以下五个优先考虑事项&#xff1a; 以面向未来的眼光进行架构开发——对SOA实施来说&#xff0c;最需…...

忻州网站建设网站推广/微信搜一搜seo优化

1. 简介 对于cocos2dx的分辨率方案原来一知半解&#xff0c;终于今天有机会给搞清楚了。在cocos2d-x中的几种分辨率&#xff1a; 1.1 Framebuffer分辨率&#xff08;其大小依赖于硬件设备&#xff09; 保存在EGLViewProtocol类的Size _screenSize; 在nativeactivity.cpp的coco…...

wordpress孵化器主题/济宁百度推广开户

事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性&#xff0c;称为 ACID&#xff08;原子性、一致性、隔离性和持久性&#xff09;属性&#xff0c;只有这样才能成为一个事务。事务管理特性&#xff0c;强制保持事务的原子性和一致性。事务启动之后…...

日语网站设计/十大软件免费下载网站排行榜

c语言没有String类型&#xff0c;更没有String.length()方法&#xff0c;那么要怎么求数组长度呢&#xff1f; 数组举例&#xff1a;int arr[]{2,3,1,4}, char str[]{“Hello”} 获得数组长度可以用这个方法&#xff1a; 比如int数组 sizeOf(arr)/sizeOf(int) 可以求出数组长…...

郑州网站建设哪家好/全网搜索引擎

题意 分析 这个题目还是很优秀的。sigma(len(Ti)len(Tj))的值是一定的n*(n1)*(n-1)/2。那么关键就是求任意两个后缀的lcp的和了。 我们怎么求两个后缀的lcp&#xff1f;如果用后缀自动机的话&#xff0c;我们可以先把字符串反过来&#xff0c;然后建后缀自动机&#xff0c;那么…...

网上拿手工做的网站/淘宝seo优化排名

作业要求&#xff1a; 做一个MP3文件播放器。具体要实现的是程序能够打开MP3文件&#xff0c;并可以播放这个文件。控制台程序或是gui程序都可以。gui是Graphical User Interface的简写&#xff0c;简单理解就是窗口的意思。思路&#xff1a;1、程序要知道文件的路径&#xff0…...