高性能MySQL实战(二):索引

2023-11-20

我们在上篇 高性能MySQL实战(一):表结构 中已经建立好了表结构,这篇我们则是针对已有的表结构和搜索条件为表创建索引。

1. 根据搜索条件创建索引

我们还是先将表结构的初始化 SQL 拿过来:

CREATE TABLE `service_log` (
  `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
  `service_type` smallint NOT NULL DEFAULT -1 COMMENT '接口类型',
  `service_name` varchar(30) DEFAULT '' COMMENT '接口名称',
  `service_method` tinyint NOT NULL DEFAULT -1 COMMENT '接口方式 1-HTTP 2-TCP',
  `serial_no` int DEFAULT -1 COMMENT '消息序号',
  `service_caller` tinyint DEFAULT -1 COMMENT '调用方',
  `service_receiver` tinyint DEFAULT -1 COMMENT '接收方',
  `status` tinyint DEFAULT 10 COMMENT '状态 10-成功 20-异常',
  `error_message` varchar(200) DEFAULT '' COMMENT '异常信息',
  `message` varchinar(1000) DEFAULT '' COMMENT '报文内容',
  `create_user` varchar(50) DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_user` varchar(50) DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `is_delete` tinyint NOT NULL DEFAULT 0 COMMENT '刪除标志',
  `ts` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '时间戳',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='接口调用日志';

现有如下搜索条件:

  1. 根据 接口名称 来搜索对应的调用日志
  2. 根据 状态 查询成功或异常的调用日志
  3. 根据 接口名称状态 查询调用日志
  4. 根据 消息序号 来获取一组调用日志
  5. 根据 创建时间 的时间范围查询调用日志
  6. 根据 报文内容 查询调用日志

索引是提升查询性能最有效的手段,它可以快速定位到记录,大大减少需要扫描的数据量,将随机 I/O 变为顺序 I/O,而且 B+ Tree 索引会根据索引值顺序存储,所以也能够应用于 排序和分组

为了在查看这些接口调用日志时有更好的体验,那么我们就需要根据搜索条件来创建索引。

索引的类型尽量小

我们先关注下接口名称的搜索条件,我们可以发现:接口名称和接口类型这两个字段都能查询到相同类型接口的日志数据,只不过它们的类型不同,前者是字符串类型,后者是整型。

这时我们需要注意:选择创建索引的列的类型要尽量小。因为每创建一个索引就相当于创建了“一棵 B 树”,数据类型越小,那么索引占用的存储空间就越少,在一个数据页内就能存放更多的记录,因此磁盘 I/O 带来的性能损耗也就越少

除此之外,在 MySQL 内部整型数据的比较相比于字符串类型的比较更简单,效率也更高。所以,我们会选择为接口类型创建索引而不是为接口名称创建索引。

接口类型 列添加索引的 SQL 如下:

alter table service_log add index index_service_type(`service_type`);

根据条件 4,消息序号列也需要添加索引:

alter table service_log add index index_serial_no(`serial_no`);

冗余和重复索引

同样地,根据搜索条件 2,我们为状态列添加上索引:

alter table service_log add index index_status(`status`);

这时,我们再看看条件 3,需要为接口类型和状态添加 联合索引。不过需要注意的是:该联合索引和已经添加的接口类型索引是重复索引,根据联合索引的 最左匹配原则,第一列为接口类型的联合索引同样能为查询条件只有接口类型的查询服务,所以我们需要将原有为接口类型添加的索引删掉,再创建新的接口类型和状态的联合索引。

-- 删除 index_service_type
alter table service_log drop index index_service_type;

-- 添加联合索引
alter table service_log add index index_service_type_status(`service_type`, `status`);

创建联合索引时有一个重要的经验性法则:将列值重复率最低的放到索引的最前列。如果重复的值过多,那么扫描到的数据行数也就越多,这样就会使得回表的压力很大。

通常情况下,把 WHERE 条件里面的列都独立地创建多个单列索引,在大部分情况下并不能提高MySQL的查询性能。我们应该尽可能的去考虑 索引列的顺序 或者创建一个 全覆盖索引

为重复率低的列创建索引

在我们的实际业务中,接口调用的状态几乎所有都是成功,很少会出现失败的情况,所以这时我们为状态列创建索引并不是很合适。因为如果我们查询所有状态为成功的数据,那么它可能会执行太多次的回表操作,导致查询效率下降,可能还不如执行全表扫描来的快。但是我们再考虑另一种情况,有时我们会根据状态为失败的记录做业务分析或排查问题,失败的数据是比较少的,如果我们通过索引查询就会非常高效,所以该列索引还有必要保留。

只不过我们在这里需要做一个处理:如果状态为成功时,我们为生成的 SQL 语句添加上忽略索引的关键字 ignore index(index_name) ,那么这样我们就能达到在查询成功状态的数据时全表扫描,而在查询失败状态的数据时使用索引了。

select * from service_log ignore index(index_status)
where status = 10;

全值匹配和按值范围匹配的时间列

条件 5 根据创建时间来进行全值匹配和按值范围匹配 非常适合创建索引:

alter table service_log add index index_create_time(`create_time`);

全文索引

FULLTEXT 全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引中的值,更类似于搜索引擎所做的事情。在查询时适用于 MATCH AGAINST 操作,而不是普通的 WHERE 条件。

对于条件 5,我们需要在接口请求的报文中根据关键字,比如说包裹号来查询特定的数据,这就使得我们需要为报文内容列创建全文索引,SQL 如下:

alter table service_log add fulltext fulltext_message(`message`);

-- 执行查询时的语句
select * from service_log where match(message) against('123456');

全文索引在日常使用的并不多,它有许多需要注意的细节,如停用词、词干、复数和布尔搜索等,具体的详情信息可以查看文末的参考文献。

那么,最终初始化表结构的 DDL 语句如下:

CREATE TABLE `service_log` (
  `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
  `service_type` smallint NOT NULL DEFAULT -1 COMMENT '接口类型',
  `service_name` varchar(30) DEFAULT '' COMMENT '接口名称',
  `service_method` tinyint NOT NULL DEFAULT -1 COMMENT '接口方式 1-HTTP 2-TCP',
  `serial_no` int DEFAULT -1 COMMENT '消息序号',
  `service_caller` tinyint DEFAULT -1 COMMENT '调用方',
  `service_receiver` tinyint DEFAULT -1 COMMENT '接收方',
  `status` tinyint DEFAULT 10 COMMENT '状态 10-成功 20-异常',
  `error_message` varchar(200) DEFAULT '' COMMENT '异常信息',
  `message` varchar(1000) DEFAULT '' COMMENT '报文内容',
  `create_user` varchar(50) DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_user` varchar(50) DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `is_delete` tinyint NOT NULL DEFAULT 0 COMMENT '刪除标志',
  `ts` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '时间戳',
  PRIMARY KEY (`id`),
  index index_serial_no(`serial_no`),
  index index_status(`status`),
  index index_create_time(`create_time`),
  index index_service_type_status(`service_type`, `status`),
  fulltext fulltext_message(`message`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='接口调用日志';

前缀索引

一般情况下,对于 VARCHAR、BLOB 和 TEXT 等相关类型的列创建索引时,为了提升索引的性能和节省索引空间,会只对字段的前一部分字符进行索引,不过这样做的缺点是使得索引的选择性降低。

索引的选择性是指不重复的索引值和记录总数的比值,可以理解为重复率越低选择性越高,唯一索引的选择性为 1。

在我们的数据库表示例中,并没有字段适合建立前缀索引。其中报文内容列也并不适合创建前缀索引,因为这些报文的前缀都很相似,而且我们在执行查询时并不会带上前缀,而是只使用关键词信息查询。

但是,前缀索引比较重要,所以我们在这里也对创建前缀索引的方法介绍一下。

MySQL 并不支持对这些长字符类型列的完整内容进行索引,我们选择前缀长度的关键点在于:既要保证选择足够长的前缀使得选择性较高,同时又不能太长防止占用太多的空间。

可以根据如下方法来确定前缀的长度:

首先,查看要添加索引的列出现最频繁的一些值:

select count(0) as c, specific_column
from specific_table
group by specific_column
order by c desc
limit 10;

之后先从 3 个前缀字母开始匹配尝试:

select count(0) as c, left(specific_column, 3) as pref
from specific_table
group by pref
order by c desc
limit 10;

慢慢地增加前缀长度,直到这个前缀的选择性接近我们首次查询的完整列的选择性即可。

或者,采用如下的方法,先计算出完整列的选择性:

select count(distinct specific_column) / count(0)
from specific_table;

然后分别计算不同前缀的选择性,直到找到与完整列接近的选择性前缀长度即可:

select count(distinct left(specific_column, 3)) / count(0) as sel3,
count(distinct left(specific_column, 4)) / count(0) as sel4,
count(distinct left(specific_column, 5)) / count(0) as sel5,
count(distinct left(specific_column, 6)) / count(0) as sel6,
count(distinct left(specific_column, 7)) / count(0) as sel7
from specific_table;

不过,也有例外的情况,那就是即使现在我们选择了比较接近完整列选择性的前缀,但数据的分布仍然很不均匀。

这时我们需要用该前缀执行如下查询,并与完整列查询出的数目作比较,观察这些出现频率最高的前缀值与完整列出现频率是否接近,否的话需要再将前缀值调大。

select count(0) as c, left(specific_column, 5) as pref
from specific_table
group by pref
order by c desc
limit 10;

-- 完整列的出现频率
select count(0) as c, specific_column
from specific_table
group by specific_column
order by c desc
limit 10;

最后,找到合适的前缀数创建前缀索引可以使用如下 SQL:

alter table specific_table add index index_specific_column(specific_column(7));

虽然前缀索引能够使索引更小,更快,但是我们不能使用前缀索引做 ORDER BY 和 GROUP BY 操作,也无法使用前缀索引做索引覆盖。

2. 关于索引必须知道的事儿

下文中我们所说的索引如果没有特别指明类型,那么就代表我们说的是 B+ Tree 索引,它使用 B+ Tree 数据结构来保存数据。

B+ Tree 会将所有的数据保存在叶子节点上,并且通过双向链表将叶子节点连接起来。

聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式,InnoDB 聚簇索引在数据页中同时保存索引和数据行,这使得它的数据访问相比于非聚簇索引(二级索引)要快。

聚簇的意思是说 数据行和相邻的键值紧凑的存储在一起,因为无法同时把数据行放在两个不同的地方,所以一个表只能有一个聚簇索引。InnoDB 根据 主键 聚簇数据,如果没有定义主键,InnoDB 会自动生成一个唯一的隐式主键作为聚簇索引。

我们创建一个简单的表,并插入一些数据,来看一下 B+ Tree 索引的数据结构图:

create table demo (
    c1 int,
    c2 int,
    c3 char(1),
    primary key(c1)
)engine=InnoDB;

MySQL 是通过 数据页 来保存数据的,每个页的大小默认为 16KB,在每个数据页中都默认有最小记录 Infimum 和最大记录 Supremum,如下图所示:

BTree.png

我们可以发现在叶子节点中保存了所有数据行,每个页之间通过页文件头部(File Header)记录的双向链表指针进行连接,数据记录之间通过单向链表连接,单向链表的指针记录在每行数据记录的 记录头信息 中。

在非叶子节点中,我们可以发现记录的信息只有 主键值和对应的页号,因此数据页能存放的数据更多,B+ Tree 也就能更加 “矮胖”,这样就能使得磁盘 I/O 更少。一般情况下我们用到的 B+ Tree 不会超过 4 层。

B+ Tree 按照索引列数据的大小顺序排序存储,所以很适合按照范围来查询。每次搜索数据都从索引的根节点开始,通过比较节点中的值和要查找的值来找到合适的指针进入下层子节点,最终在叶子节点中找到或找不到对应的记录。

聚簇索引能够加快我们访问数据的速度,但是它也有一些局限性我们需要了解一下:

  • 聚簇索引最大限度地提高了 I/O 密集型应用的性能,但如果 数据全部都放在内存中,则访问的顺序就没那么重要了,聚簇索引也就没什么优势了

    随着 RAM 变得更便宜,而且许多数据集不是那么大,所以将它们全部保存在内存中是非常可行的,包括可能分布在多个服务器上,这也促进了内存数据库的发展。

  • 插入速度严重依赖于插入顺序。按照主键的顺序插入行是将数据加载到 InnoDB 表中最快的方式。但如果不是按照主键的顺序插入,会因页分裂影响插入速度。最好避免随机的聚簇索引,特别是对于 I/O 密集型的应用

  • 聚簇索引列更新的代价很高,因为它会强制 InnoDB 将每个被更新的行移动到新的位置,这也会发生页分裂,导致性能下降

二级索引

二级索引是非聚簇索引,InnoDB 引擎在 B+ Tree 的叶子节点存储的不是完成的数据记录,而只是 索引列和主键列的值。如果在查询时没有发生覆盖索引的话,需要根据主键值进行回表操作以获取需要的结果。

二级索引是关系型数据库的基础,并且在文档数据库中也很普遍。许多键值存储(如 HBase 和 Volde-mort)为了减少实现的复杂度而放弃了二级索引,但是一些(如 Riak)已经开始添加它们,因为它们对于数据模型实在是太有用了。并且次级索引也是 Solr 和 Elasticsearch 等搜索服务器的基石。

实际上,有两种用二级索引对文档数据库进行分区的方法:基于文档(document-based) 的分区 和 基于关键词(term-based) 的分区。

*基于文档的分区

假设我们有一个汽车销售网站,每条数据都有唯一的 ID,我们称之为文档 ID。我们使用文档 ID 进行分区,并为汽车颜色字段创建二级索引,分区结果如下图所示:

文档分区.png

这样的二级索引分配方法,使得每个分区都是独立的:每个分区自己维护自己的索引,它不关心其他分区的数据,这种文档分区索引也被称为 本地索引

当我们查询红色的汽车时,需要将请求发布到所有的分区,并合并所有返回的结果,这种查询数据库的方法被称为 分散/聚集,可能会使得二级索引查询数据比较耗时。

*基于关键词的分区

我们也可以构建一个覆盖所有分区数据的 全局索引,比如我们将 a 到 r 开头的颜色的二级索引保存在分区 0 中,将 s 到 z 的保存在分区 1 中,如下图所示:

关键词分区.png

我们将这种分区方法称为 关键词分区,根据关键词本身分区对于范围扫描非常有用,比如说我现在想获取 a 到 r 开头的颜色的所有汽车数据;而对关键词的哈希分区又能够提供分区负载均衡的能力。

基于关键词分区的全局索引优于文档分区索引的地方在于它的读取更加高效,并不需要将请求打到所有分区上,只需要将请求发送到含有对应关键词的分区即可,而它的缺点在于对单个分区文档的写入可能会产生多个分区的索引的数据变更,需要协调跨分区的分布式事务。

覆盖索引

覆盖索引可以简单地理解成 查询只需要访问索引列而无需访问其他数据列

优秀的索引设计不单单只考虑 WHERE 条件,也会根据想要查询的列去综合分析。如果只需要索引列的话,那么覆盖索引是非常有用的工具,它能避免回表操作,这样 MySQL 就会极大地减少数据访问量,而且索引占用的空间很小,将这些数据缓存在内存中的压力远小于缓存所有相关数据行。

如果业务无需查询其他列,那么我们最好把业务需要的列放在查询列表中,以实现覆盖索引,而不是简单地以 * 来替代;在某些情况下,可以根据想要查询的列,对所使用的索引进行扩展,即增加想要查询的列达到覆盖索引的目的。

当执行一个覆盖索引的查询时,在 EXPLAIN 的 Extra 列可以看到 Using index 的信息。

自适应哈希索引

它是 InnoDB 的一个特性,当 InnoDB 发现某些索引值被非常频繁的访问时,它会在原有的 B+ Tree 索引之上,再在内存中构建一个哈希索引,以此来加快对应数据的访问。这个过程是自动化的,我们无法进行干预,不过可以通过参数配置将其关闭。


巨人的肩膀

  • 《数据密集型应用系统设计》:第三章、第六章
  • 《高性能 MySQL 第四版》:第七章
  • 《MySQL 是怎样运行的》:第四、五、六、七章
  • 14.6.2.4 InnoDB Full-Text Indexes

作者:京东物流 王奕龙

来源:京东云开发者社区 自猿其说Tech 转载请注明来源

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高性能MySQL实战(二):索引 的相关文章

  • Android PhoneGap 插件,UI 选项卡栏,调整 WebView 大小

    我正在创建一个美味的 PhoneGap 插件 希望一旦它能被打开 准备好了 插件基本完成了 我只需要一个漂亮的用户界面 相互作用 简而言之 我想创建一个 本机 android 工具栏组件 如果您实现 PhoneGap UIControls
  • onScale 事件后触发奇怪的 onScroll 事件

    我有一个同时使用 SimpleOnScaleGestureListener 和 SimpleOnGestureListener 的应用程序 每当我进行捏缩放时 我都会得到预期的 onScale 但是当我抬起时 我会看到一个奇怪的 onScr
  • 当不支持 Google Play 应用内结算 V.3 时

    在 Google Play 的应用内结算 V 3 中 有一个选项可以检查用户设备是否支持它 使用是否支持计费 http developer android com google play billing versions html meth
  • 如何向开发人员发送崩溃报告?

    我开发 Android 应用程序 但在某些情况下我的应用程序force close 如果出现以下情况 我如何向开发人员发送包含详细信息的电子邮件force close随时发生 The ACRA https github com ACRA a
  • Android中如何检测WIFI连接何时建立?

    我需要检测何时通过 WIFI 建立网络连接 发送什么广播来确定已建立有效的网络连接 我需要验证是否存在有效的 HTTP 网络连接 我应该监听什么以及需要进行哪些额外测试才能知道是否存在有效连接 您可以注册一个BroadcastReceive
  • Android 版 jTwitter 授权错误

    我在我的 Android 应用程序中使用 jTwitter 库 直到前天一切都运转良好 但今天遇到异常 服务提供商响应错误 301 请帮助我 这是堆栈跟踪 02 21 21 07 27 258 E AndroidRuntime 4013 F
  • MySQL 数据库无法在 XAMPP for Mac 上启动

    突然我在 mac 上遇到了这个问题 我无法启动我的 MySQL 数据库 我只能启动 ProFTPD 和 Apache Web Server 这是应用程序日志 Starting all servers Starting MySQL Datab
  • 如何在 NumberPicker 中一次显示 3 个以上的值

    我正在创建一个数字选择器 如下图所示 但如果有可用空间 我想显示 3 个以上的值 该选择器有 20 个项目 并且有足够的空间来显示 3 个以上的值 这可以使用 NumberPicker 来完成吗 只需以编程方式设置numberPicker
  • 使用 Android Studio 进行调试永远停留在“等待调试器”状态

    UPDATE The supposed重复是一个关于陷入 等待调试器 执行时Run 而这个问题就陷入了 等待调试器 执行时Debug 产生问题的步骤不同 解决方案也不同 每当我尝试使用Android Studio的调试功能时 运行状态总是停
  • Android 时钟滴答数 [赫兹]

    关于 proc pid stat 中应用程序的总 CPU 使用率 https stackoverflow com questions 16726779 total cpu usage of an application from proc
  • 日期时间与时间戳字段

    我是 MySQL 数据库的新手 您是否建议在表创建中使用日期时间或时间戳字段以及原因 我正在使用 MySQL 5 7 和 innodb 引擎 Thanks 我会用TIMESTAMP对于任何需要自动管理的事情 因为它支持诸如ON UPDATE
  • mysql表中的数据非常大。即使 select 语句也需要很多时间

    我正在开发一个数据库 它是一个相当大的数据库 有 13 亿行和大约 35 列 这是我检查表状态后得到的结果 Name Table Name Engine InnoDB Version 10 Row format Compact Rows 1
  • Glass 语音命令给定列表中最接近的匹配项

    使用 Glass 您可以通过 确定 Glass 菜单启动应用程序 它似乎会选择最接近的匹配项 除非命令相距数英里 并且您可以明显看到命令列表 无论如何 是否可以从应用程序内或从语音提示 在初始应用程序触发后 给出类似的列表并返回最接近的匹配
  • 如何在 Android 上将动态 alpha 遮罩应用于文本

    I want to make a dynamic alpha mask with drawable shapes as circles or whatever and apply it to a drawed text on Android
  • 由于“进程崩溃”,仪器运行失败。

    我想运行以下测试 package com xxx yyy import android content Context import androidx test InstrumentationRegistry import androidx
  • PDO语法错误

    我在一个项目中使用 PDO 但提交时出现语法错误 这是我的代码
  • Flash 对象未显示在phonegap android 中

    我已经在 android 手机间隙创建了一个应用程序 我有一个屏幕 我想显示一个静态 flash obj 所以我在屏幕 HTML 页面中放入了以下代码
  • 如何正确编写AttributeSet的XML?

    我想创建一个面板适用于 Android 平台的其他小部件 http code google com p android misc widgets 在运行时 XmlPullParser parser getResources getXml R
  • 更改mysql数据库表中的日期格式

    大家早上好 只是一个简单的问题 在我现有的 MySql 数据库中 我几乎没有包含日期 的列 目前这些是年 月 日格式 但现在我需要将其全部更改为年 月 日格式 我试过了select date format curdate d m Y 但它不
  • 在同一查询中选择 Count of ip 和 Count of DISTINCT ip

    我有一个这样的表结构 TABLE NAME counter id datetime url ip 1 2013 04 12 13 27 09 url1 ip01 2 2013 04 13 10 55 43 url2 ip02 3 2013

随机推荐

  • matlab 怎么使用function,Matlab怎么调用函数 自定义函数使用方法

    Matlab作为一款专业性极强的商业数学软件 将诸多的算法开发 统计分析 数据可视化功能融入其中 用户可以方便地调用需要的函数 建立数学模型 为了满足你工作的需要 还可以自行设置自己需要的函数 下面就跟小编了解下吧 类别 理科工具 大小 1
  • Unix Network Programming Episode 77

    gethostbyaddr Function The function gethostbyaddr takes a binary IPv4 address and tries to find the hostname correspondi
  • time_wait的快速回收和重用

    问题现象 PC与工控机之间通信 工控机发送SYN PC一直回复FIN或者RST 问题解释 1 time wait产生的原因及作用 下面我们先来简单回顾一下TCP连接关闭动作 在Linux环境下我们可以如下的方式来统计TCP连接的情况 net
  • 高防服务器如何防止网站攻击,高防服务器怎么防御攻击的?

    高防服务器怎么防御攻击的 高防服务器 从字面上来理解就是具备防御性能的服务器 高防服务器相较于普通的服务器除了超高的防御性能以外 在配置上通常也是比较高的 所以在使用上 会更稳定一些 所以深受各类行业站长的喜爱 如今 很多企业在选择租用服务
  • C语言之冒泡排序法

    首先 还是老规矩先上代码 include
  • 数组双指针法汇总

    指针移动方向 相向夹逼 同向移动 维护的是一个区间还是只是关心指针指向的两个元素 同向移动的 维护一个区间的双指针法即滑动窗口法 2Sum 排序后两头往中间夹逼的双指针法 指针为什么可以不回退 即为什么可以i只 j只 当A i A j
  • jvm学习——7.运行时数据区之堆

    一个进程对应一个jvm实例 一个运行时数据区 又包含多个线程 这些线程共享了方法区和堆 每个线程包含了程序计数器 本地方法栈和虚拟机栈 66 核心概述 1 一个jvm实例只存在一个堆内存 堆也是java内存管理的核心区域 2 Java堆区在
  • kuboard获取token命令

    输入命令查看 echo kubectl n kube system get secret kubectl n kube system get secret grep kuboard user awk print 1 o go templat
  • u8系统怎么连接服务器,u8客户端连接服务器流程

    u8客户端连接服务器流程 内容精选 换一换 请点击下载 下载并安装桌面版客户端 您已经从企业的会议管理员那儿获取用户帐号了吗 快使用用户帐号登录客户端 开启会议之旅 桌面客户端定位基于电脑使用 在会议室中不支持接入鹅颈麦克风 音箱等外设使用
  • QT的QListWidget之单击双击增删改详解

    QListWidget是列表框控件 它是通过QListWidgetItem列表项来进行操作 我们的增删改操作也是围绕着它来开展 需要注意的是 删除操作 需要先断开QListWidget的信号和槽连接 否则会程序崩溃 void MainWin
  • opencv畸变校正的两种方法

    opencv中畸变校正有两种方法 1 undistort 直接进行畸变校正 void cv undistort InputArray src 原始图像 OutputArray dst 矫正图像 InputArray cameraMatrix
  • echarts中的地图展示所有省份以及悬浮上去展示具体的信息

  • stm32 HAL库 Flash操作简介

    stm32 HAL库 Flash操作简介 目录 第一stm32 flash介绍 查看代码段 以判断代码长度 flash的基本操作规则 stm32 HAL库 Flash操作指南 stm32f1xx hal flash c stm32f1xx
  • 在家做什么手工赚钱,这5种比较适合在家操作!

    对于很多怀孕的女生来说 呆在家里确实很无聊 大部分人呆在家里只能看看电视 玩玩手机 很多的孕妈都会抱怨 真是无聊透了 所以对于很多的孕妈来说 都想找点事做来缓解自己无聊的情绪 避免得了抑郁症 给宝宝带来不好的环境 那么怀孕在家里 有什么轻松
  • SpringSecurity的使用和流程详解(二)

    文章目录 登录 准备工作 核心代码 校验 准备工作 核心代码 测试 退出登录 登录 准备工作 添加依赖
  • 线程池代码

    线程池 Global h pragma once const int DEFAULT POOL SIZE 10 const int STARTED 0 const int STOPPED 1 Mutex h pragma once incl
  • 鸡肋的RDP反制

    更新时间 2023年07月19日09 18 29 为什么叫鸡肋 鸡肋者 食之无肉 弃之有味 你说不能成吧 但是有成功案例 你说成了吧 要求太高 还要看运气的 一句话 对方需要开启磁盘共享 不开启 没办法反制 1 背景介绍 在很多攻防中 蓝队
  • 向量叉乘判断顺时针还是逆时针

    可以通过向量的叉乘判断一条线旋转的过程是顺时针还是逆时针的 有两个向量AB和AC 将两个向量进行叉乘 direct AB x AC 当direct gt 0时 为逆时针旋转 当direct lt 0时为顺时针旋转 当写类似于旋转按钮的控件的
  • 螺纹检测案例-螺距测量-大径小径检测-螺牙检测

    齿轮检测分析 Gear inspection and analysis 螺纹结构及检测要素 1 大径 宽径 2 小径 窄径 3 中经 4 螺距 间距 5 螺牙高度 深度 VisionBank 软件螺纹检测工具 02 01 螺纹检测分析流程
  • 高性能MySQL实战(二):索引

    我们在上篇 高性能MySQL实战 一 表结构 中已经建立好了表结构 这篇我们则是针对已有的表结构和搜索条件为表创建索引 1 根据搜索条件创建索引 我们还是先将表结构的初始化 SQL 拿过来 CREATE TABLE service log