《深入浅出MySQL:数据库开发、优化与管理维护(第3版)》
深入浅出MySQL
- sql执行流程
- 第一步:通过连接器进行连接
- 第二步:解析器解析 SQL
- 第三步:执行SQL
- 行记录存储格式
- 行溢出
- 日志
- 数据库三大范式
- 第一范式
- 第二范式
- 第三范式
- 索引
- 索引分类
- B+树索引
- B+Tree vs Hash
- 需要索引
- 1、字段需要频繁的查询操作
- 2、字段用于排序和分组的
- 3、字段有唯一性约束的
- 不需要索引
- 1、表数据太少
- 2、经常更新的字段
- 3、字段存在大量重复数据
- 索引失效情况
- 1、对索引使用左、左右模糊查询
- 2、对索引进行表达式计算
- 3、联合索引非最左匹配
- 4、WHERE 中 OR前和OR后
- 2、事务
- ACID
- 1、脏读
- 2、不可重复读
- 3、幻读
- 事务隔离级
- MVCC
- 3、锁
- 1、全局锁
- 2、表级锁
- 1、元数据锁(MDL)不需要显示调用
- 2、意向锁
- 3、行级锁
- 1、Record Lock,记录锁
- 2、Gap Lock,间隙锁
- 3、Next-Key Lock,临键锁
- 4、InnoDB 与 MyISAM
sql执行流程
MySQL 的架构共分为两层:上层的Server 层和下层的存储引擎层
Server 层主要负责建立连接、分析和执行 SQL。存储引擎层主要负责数据的存储和提取。
第一步:通过连接器进行连接
我们首先需要连接 MySQL 服务器,然后才能执行 SQL。因为 MySQL 是基于 TCP 协议进行传输的,所以连接的过程需要先经过 TCP 的三次握手。
查询缓存
如果 SQL 是查询语句,MySQL 就会先去缓存里查找缓存数据,查询缓存是以 key-value 形式保存在内存中的。
如果查询的语句命中查询缓存,那么就会直接返回 value 给客户端。如果查询的语句没有命中查询缓存中,那么就要往下继续执行,等执行完后,查询的结果就会被存入查询缓存中。
但其实对于更新比较频繁的表,查询缓存的命中率很低的,所以,MySQL 8.0 版本直接将查询缓存删掉了。
第二步:解析器解析 SQL
在正式执行 SQL 查询语句之前, MySQL 会先对 SQL 语句做解析,这个工作交由「解析器」来完成。
词法和语法分析。MySQL 会根据输入的字符串识别出表名,字段名这些关键字。然后检验我们输入的 SQL 语句语法是否正确,比如把 from 写成了 form,这时 MySQL 解析器就会报错。
第三步:执行SQL
SELECT 查询语句流程主要可以分为三个阶段:
1、预处理阶段;
检查 SQL 查询语句中的表或者字段是否存在;把 select* 中的 * 符号,扩展为表上的所有列;
2、优化阶段;
优化器主要负责确定 SQL 查询语句的执行方案,比如在表里面有多个索引的时候,优化器会基于查询成本的考虑,来决定选择使用哪个索引。
3、执行阶段;
根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;
连接器— 解析器 — 执行器
行记录存储格式
InnoDB 提供了 4 种行格式,比较经典的是Compact格式。
在compact行格式下,一行记录分为两个部分:额外信息和真实数据。
额外信息
3 个部分:变长字段的长度列表、NULL 值列表、记录头信息
变长字段的长度列表主要是存储变长字段所占用的数据大小,然后读取的时候根据这个长度列表来读取对应的数据长度。
(如果表里没有变长字段,那行格式就不会有变长字段长度列表)
NULL 值列表:因为表中的某些列可能会存储 NULL 值,如果把这些 NULL 值都放到记录的真实数据中会比较浪费空间,所以 Compact 行格式把这些值为 NULL 的列存储到 NULL值列表中。(如果字段都是 NOT NULL,就不会有 NULL 值列表)
记录头信息:主要包含标识这条数据是否被删除、下一条记录的位置等等。
真实数据
记录真实数据部分除了我们定义的字段,最前面还有三个隐藏字段,分别为:row_id、trx_id、roll_pointer。
如果表里既没有指定主键,又没有唯一约束,那么 InnoDB 就会为记录添加 row_id 隐藏字段,占六个字节。
trx_id是事务id,表示这个数据是由哪个事务生成的,占6个字节。
roll_pointer,这条记录上一个版本的指针。roll_pointer 是必需的,占 7 个字节。
行溢出
MySQL 中磁盘和内存交互的基本单位是页,一个页的大小一般是 16KB,也就是 16384字节,而一个 varchar 类型的列最多可以存储 65532字节,一些大对象如 TEXT、BLOB 可能存储更多的数据,这时一个页可能就存不了一条记录。这个时候就会发生行溢出,多的数据就会存到另外的「溢出页」中。
日志
undo log 回滚日志:是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC多版本并发控制。
在每个事务的执行过程中,都记录下回滚时需要的信息到一个日志里,那么在事务执行中途发生了 MySQL 崩溃后,我们可以通过这个日志回滚到事务之前的数据。
redo log 重做日志:是 Innodb 存储引擎层生成的日志,实现了事务中的持久性,主要用于断电等故障恢复;
redo log 它记录了某个数据页做了什么修改,比如对表空间A中的B数据页C偏移量的地方做了更新,每当执行一个事务就会产生这样的一条或者多条物理日志。
在事务提交时,会先把 redo log 持久化到磁盘。当系统崩溃 MySQL 重启后,可以根据 redo log 的内容,把所有数据恢复到最新的状态。
undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值;
redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;
binlog 归档日志:是 Server 层生成的日志,主要用于数据备份和主从复制;
MySQL 在完成一条更新操作后,Server 层还会生成一条 binlog,等之后事务提交的时候,会将该事务执行过程中产生的所有 binlog 统一写 入 binlog 文件。
binlog 文件是记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。
数据库三大范式
第一范式
所谓第一范式是指数据库表的每一列都不能再分,也就是某个属性不能有多个值。简而言之,第一范式就是无重复的列。比如某条记录里小明的课程字段有数学语文英语,那就应该分为三条记录。
第二范式
满足第二范式必须先满足第一范式,第二范式要求数据库表中的每行必须可以被唯一地区分。这个唯一区分的方法通常是给表加上一个存储唯一标识的列,其实也就是主键。简而言之,第二范式就是有主键,非主键字段依赖主键。
第三范式
满足第三范式必须先满足第二范式。第三范式要求一个在数据库表中不能包含其它表中的非主关键字。
部门表里有ID、name,ID是主键。
那么在员工表里,最多只能加入部门ID,而不能再加入部门名称等字段,否则就会有大量的数据冗余。
简而言之,第三范式就是属性不依赖于其它非主属性。
索引
索引的定义就是帮助存储引擎快速获取数据的一种数据结构,形象的说索引就相当于数据的目录。
索引分类
- 按「数据结构」分类:B+tree索引、Hash索引、Full-text索引。
- 按「物理存储」分类:聚簇索引、二级索引
B+树索引
B+Tree 是一种多叉树,特点是只在叶子节点中按主键顺序放数据(主键值或实际数据),在非叶子节点中只放索引。每一个叶子节点都有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成一个双向链表。
每一层父节点的索引值都会出现在下层子节点的索引值中,因此在叶子节点中,包括了所有的索引值信息。
B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率很高。
- 因为B+Tree 只在叶子节点存储数据,非叶子只放索引,所以它每个非叶子节点可以存储更多的索引键值对,所以从根节点到叶子节点的路径更短,在相同的磁盘 I/O 次数下,就能查询更多的节点。
- 而且由于它的叶子节点是按有序链表连接的,因此在进行范围查询的时候,可以通过一次I/O操作访问多个相邻的数据。因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 效率依然很高。
一张表只能有一个聚簇索引,那就还会有非聚簇索引,非聚簇也是用了 B+ 树的数据结构,只不过非聚簇索引的叶子节点存放的是主键值,不是实际数据。
聚簇索引的 B+Tree 和非聚簇索引的 B+Tree 的区别
主键索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里;
二级索引的 B+Tree 的叶子节点存放的是主键值,而不是实际数据。查询时需要先获得主键值,再通过主键索引中的 B+Tree 树查询到对应的叶子节点来获取整行数据。这个过程叫「回表」,也就是说要查两个 B+Tree 才能查到数据。
MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址,也就是一个指向对应数据块的指针。
B+Tree vs Hash
Hash 在做等值查询的时候效率很快,搜索复杂度为 O(1)。但数据库中经常查询多条数据,这时候由于B+数据的有序性,叶子节点又有链表相连,他的查询效率会比Hash快的多。
需要索引
1、字段需要频繁的查询操作
当某个字段经常用于查询操作时,可以考虑为该字段创建索引。索引可以加快查询速度,特别是在大型数据集中。
2、字段用于排序和分组的
经常用于 GROUP BY 和 ORDER BY 的字段,这样在查询的时候就不需要再去做一次排序了,因为建立索引之后在 B+Tree 中的记录都是排序好的。
3、字段有唯一性约束的
当需要确保某个列的唯一性时,可以在该列上创建唯一索引。唯一索引可以防止重复值的插入,并提高查找的效率。
不需要索引
索引缺点
创建和维护索引也需要时间和空间,而且时间和空间复杂度一般会随着数据量的增加而增大;
1、表数据太少
表数据太少的时候,不需要创建索引
2、经常更新的字段
经常更新的字段不用创建索引,因为如果索引字段频繁修改,那么维护 B+Tree的成本就会上升,会影响数据库性能的。
3、字段存在大量重复数据
字段中存在大量重复数据,比如性别字段,男女的记录分布均匀,那么无论搜索哪个值都可能得到一半的数据。这种情况MySQL很可能会通过查询优化器进行全表扫描。
索引失效情况
1、对索引使用左、左右模糊查询
使用 like 关键字进行左查询或者左右模糊查询会导致索引失效。因为索引底层是 B+ 树,它是按照「索引值」有序排列存储的,所以只能根据前缀进行比较。如果使用 like ‘%XX’ 方式来查询,因为查询的结果可能是「AXX、BXX、CXX」等之类的,所以不知道从哪个索引值开始比较,于是就只能通过全表扫描的方式来查询。
2、对索引进行表达式计算
查询条件中对索引进行表达式计算会使索引失效。
select* from t_user where id+1 = 10;因为索引保存的是索引字段的原始值,而不是 id + 1 表达式计算后的值,所以这样查询无法走索引。
3、联合索引非最左匹配
联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配。
如果创建了一个 (a, b, c) 联合索引
where a=1;where a=1 and b=2 and c=3;where a=1 and b=2;都可以
where c=3;where b=2 and c=3;都不行。
因为在联合索引的情况下,数据是按照索引第一列排序,第一列数据相同时才会按照第二列排序
4、WHERE 中 OR前和OR后
WHERE 子句中,如果 OR 前的条件列是索引列,而 OR 后的条件列不是索引列,那么索引会失效。因为 OR 的含义就是两个只要满足一个即可,因此只有一个条件列是索引列是没有意义的,只要有条件列不是索引列,就会进行全表扫描。
2、事务
事务是一组数据库操作的逻辑单元,用来确保数据的正确性和可靠性。
事务特性
ACID
原子性Atomicity:一个事务中的所有操作,要么全部完成,要么全部不完成。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过。
一致性Consistency:是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性的状态。比如转账时转出账户钱少了多少,那转入账户的钱就要对应多出来多少。
隔离性Isolation:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。
持久性Durability:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
并行事务会引发什么问题?
1、脏读
指如果一个事务「读到」了另一个未提交事务修改过的数据,就意味着发生了「脏读」现象。
A改了数据但是还没提交事务,B就能读到A改过的数据。如果这时A回滚了事务,那B读的数据就是过期数据,这就是脏读。
2、不可重复读
指在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。强调前后读出的数据不一致
3、幻读
不可重复读是由于另一个事务对数据的更改所造成的,而幻读是由于另一个事务插入或删除引起的。强调前后读取的记录数量不一致
事务隔离级
读未提交隔离级别下,可能发生脏读、不可重复读和幻读现象;
读已提交隔离级别下,可能发生不可重复读和幻读现象,但是不可能发生脏读现象;
可重复读隔离级别下,可能发生幻读现象,但是不可能发生脏读和不可重复读现象;
串行化隔离级别下,脏读、不可重复读和幻读现象都不可能会发生。
MySQL InnoDB 引擎的默认隔离级别是可重复读
可重复读中怎么解决幻读
针对快照读(普通 select 语句),是通过 MVCC多版本并发控制来解决了幻读的,因为在可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据保持一致,以此避免幻读问题。
针对当前读(select … for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select … for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。
MVCC
也就是多版本并发控制,MVCC主要用于解决并发控制中的读-写冲突问题,同时提供了高度的隔离性和一致性。其实通过版本链来控制并发事务访问同一个记录时的操作。
MVCC会为每个行记录都维护多个版本,每个版本都有自己的版本号和时间戳,如果有事务对记录进行修改就创建一个新的版本。当一个事务执行读取操作时,只会读取已提交的数据版本,并且不会读取其他事务正在修改的数据版本,从而避免了读-写冲突的发生。旧版本的数据对于其他正在执行的事务仍然可见,从而保持了事务的隔离性。
3、锁
在 MySQL 里,根据加锁的范围,可以分为全局锁、表级锁和行锁三类。
1、全局锁
全局锁主要应用于做全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。
但是加上全局锁,意味着整个数据库都是只读状态。
那么如果数据库里有很多数据,备份就会花费很多的时间,关键是备份期间,业务只能读数据,而不能更新数据,这样会造成业务停滞。
2、表级锁
表锁用于对整个表进行锁定,而且会限制事务对该表的访问和操作
表锁的颗粒度太大,会影响并发性能。表级锁不会出现死锁,发生锁冲突几率高,并发低。
1、元数据锁(MDL)不需要显示调用
当我们对数据库表进行操作时,会自动给这个表加上元数据锁。
元数据锁 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更。
元数据锁在事务提交后才会释放,这意味着事务执行期间,元数据锁 是一直持有的。可能会出现线程A开启了事务但还未提交(加了MDL锁),另一个修改表结构的线程会被阻塞,从而导致后续的大量select语句线程被阻塞的情况(因为写锁获取优先级高于读锁)。
2、意向锁
我们知道正常在更新记录的时候引擎会对记录加独占锁,而在InnoDB引擎中当对表里的记录加独占锁之前需要先对表加上意向独占锁,然后再对该记录加独占锁。
意向锁的目的是为了快速判断表里是否有记录被加锁。
比如有一个事务想对表里的某个记录加独占锁,它会先在表上加意向独占锁。然后如果有其他事务也考虑对同一记录加锁时就会先检查表上有没有意向独占锁。如果有,它们就知道已经有事务打算在表中的这个记录上加独占锁,就不用去遍历表里的记录了,否则还要一一遍历。
3、行级锁
不同隔离级别下,行级锁的种类是不同的。在读已提交隔离级别下,行级锁的种类只有记录锁(1)。在可重复读隔离级别下,行级锁有记录锁,还有间隙锁(123)。
行级锁会出现死锁,发生锁冲突几率低,并发高。
1、Record Lock,记录锁
锁住的是一条记录。分为有 S 共享锁和 X 排他锁,S锁之间兼容,但与X锁不兼容。X锁与S锁、X锁都不兼容。
2、Gap Lock,间隙锁
锁定一个范围,但是不包含记录本身;只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。比如表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。
3、Next-Key Lock,临键锁
Record Lock + Gap Lock 的组合,锁定一个范围,并且包含记录本身。例如表中有一个范围 id 为(3,5] 的临键锁,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录。
MySQLInnoDB引擎的行锁是通过索引加载的,也就是说,行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁,此时其它事务无法对当前表进行更新或插入操作。
4、InnoDB 与 MyISAM
1)事务:InnoDB支持事务,MyISAM不支持事务 。
2)锁级别: InnoDB 最小粒度支持行级锁,MyISAM 最小粒度支持表级锁。
3)索引:InnoDB主键索引采用聚集索引,B+树叶子存储数据;MyISAM采用非聚集索引,B+树叶子存储指向数据文件的指针。
4)外键:InnoDB支持外键,而MyISAM不支持。
适用场景:
1、InnoDB适合需要事务的场景,MyISAM适合不需要事务的场景;
2、读查询比较多的可以考虑MyISAM,如果既有读也有写使用InnoDB。
3、系统奔溃后,MyISAM恢复起来更困难;
4、如果需要使用外键,那这两个表必须是InnoDB表,因为MyISAM表暂时不支持外键。
相关文章:
《深入浅出MySQL:数据库开发、优化与管理维护(第3版)》
深入浅出MySQL sql执行流程第一步:通过连接器进行连接第二步:解析器解析 SQL第三步:执行SQL 行记录存储格式行溢出日志数据库三大范式第一范式第二范式第三范式 索引索引分类B树索引BTree vs Hash需要索引1、字段需要频繁的查询操作2、字段用…...
VBA技术资料MF171:创建指定工作表数的工作簿
我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…...
【效率提升】新一代效率工具平台utools
下载地址:utools uTools这款软件,是一款功能强大且高度可定制的效率神器,使用快捷键alt space(空格) 随时调用,支持调用系统应用、用户安装应用和市场插件等。 utools可以调用系统设置和内置应用,这样可以方便快捷的…...
Jmeter插件管理器,websocket协议,Jmeter连接数据库,测试报告的查看
目录 1、Jmeter插件管理器 1、Jmeter插件管理器用处:Jmeter发展并产生大量优秀的插件,比如取样器、性能监控的插件工具等。但要安装这些优秀的插件,需要先安装插件管理器。 2、插件的下载,从Availabale Plugins中选择ÿ…...
Android中ViewModel+LiveData+DataBinding的配合使用(kotlin)
Android 中 ViewModel、LiveData 和 Data Binding 的配合使用(Kotlin) 摘要 本文将介绍如何在 Android 开发中结合使用 ViewModel、LiveData 和 Data Binding 进行数据绑定和状态更新。我们将详细探讨这三者之间的关系,并展示如何在 Kotlin…...
Elasticsearch 避免常见查询错误和陷阱
Elasticsearch 作为一款强大的搜索引擎和分析工具,已经被广泛应用于各种场景中。然而,在使用 Elasticsearch 进行查询时,如果不注意一些常见的错误和陷阱,可能会导致查询效率低下、结果不准确甚至系统性能下降。本文旨在总结一些常…...
【PyQt】20-QTimer(动态显示时间、定时关闭)
QTimer 前言一、QTimer介绍二、动态时间展示2.1 代码2.2 运行结果 三、定时关闭3.1 介绍他的两种用法1、使用函数或Lambda表达式2、带有定时器类型(高级) 3.2 代码3.3 运行结果 总结 前言 好久没学习了。 一、QTimer介绍 pyqt里面的多线程可以有两种实…...
[深度学习] 自编码器Autoencoder
自编码器(Autoencoder)是一种无监督学习算法,主要用于数据的降维、特征提取和数据重建。自编码器由两个主要部分组成:编码器(Encoder)和解码器(Decoder)。其基本思想是将输入数据映射…...
模型微调、智能体、知识库之间的区别
使用开源模型微调和使用知识库与智能体(agent)的区别主要体现在工作原理、应用场景和实现目标上。以下是对这三者的详细对比: 开源模型微调 定义: 微调是对预训练模型(例如BERT、GPT等)进行额外训练&…...
七日世界Once Human跳ping、延迟高、丢包怎么办?
七日世界是一款开放世界为轴点的生存射击游戏,玩家将进入一个荒诞、荒芜的末日世界,在这里与好友一起对抗可怖的怪物和神秘物质星尘的入侵,给这个星球留下最后的希望,共筑一片安全的领地。不过有部分玩家在游玩七日世界的时候&…...
机器人控制系列教程之关节空间运动控制器搭建(1)
机器人位置控制类型 机器人位置控制分为两种类型: 关节空间运动控制—在这种情况下,机器人的位置输入被指定为一组关节角度或位置的向量,这被称为机器人的关节配置,记作q。控制器跟踪一个参考配置,记作 q r e f q_{re…...
[linux]sed命令基础入门详解
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这…...
Charles抓包工具系列文章(一)-- Compose 拼接http请求
一、背景 众所周知,Charles是一款抓包工具,当然是http协议,不支持tcp。(如果你想要抓tcp包,请转而使用wireshark,在讲述websocket的相关技术有梳理过wireshark抓包) 话说回来,char…...
OLMo:真正完全开源的大模型
最近,又有一家机构AI2(Allen Institute for AI)开源了一个LLM:OLMo,它的英文全称就叫Open Language Model。相比之前开源的大模型,OLMo的独特之处是完全开源,除了训练的模型,OLMo还开…...
51单片机STC89C52RC——12.1 数据存储芯片AT24C02
目的/效果 利用存储芯片AT24C02存储数据,LCD1602显示存储的数据。 一,STC单片机模块 二,AT24C02存储芯片 2.1 介绍 AT24C02是一个2K位串行CMOS E2PROM,内部含有256个8位字节,采用先进CMOS技术实质上减少了器件的功…...
融入云端的心跳:在Spring Cloud应用中集成Eureka Client
融入云端的心跳:在Spring Cloud应用中集成Eureka Client 引言 在微服务架构中,服务发现是一个关键组件,它允许服务实例之间相互发现并通信。Netflix Eureka是Spring Cloud体系中广泛使用的服务发现框架。Eureka提供了一个服务注册中心&…...
CocosCreator构建IOS的wwise教程
CocosCreator构建IOS教程 添加wwise教程: 1.添加include 2.添加SoundEngine 3.添加Profile-iphoneos下面lib下面的.a 4.导入js调用C++的文件 5.导入这些文件 6.初始化ios绝对路径和TTS语音合成对象 6.获得根目录绝对路径,加载pck需要找到绝对路径。怎么找绝对路径? #impor…...
掌握 SQL Server 中的 FLOOR 函数:数据舍入的艺术
掌握 SQL Server 中的 FLOOR 函数:数据舍入的艺术 引言 在数据分析和处理中,我们经常需要对数值进行精确控制,比如将数值舍入到特定的精度。SQL Server 提供了多种数学函数,其中 FLOOR 函数就是用来执行向上舍入操作的强大工具。…...
【折腾笔记】兰空图床使用Redis做缓存
前言 最近发现我部署在群晖NAS上的兰空图床程序在高并发的情况下会导致图片加载缓慢或出现图片加载失败的情况,于是我查阅了官方文档资料并进行了一系列的测试,发现兰空图床如果开启了原图保护功能,会非常的吃CPU的性能,尤其是在…...
【Ubuntu】如何用指令设置静态IP
这里介绍的是利用netplan 的配置文件一般在 /etc/netplan/ 目录下,文件名类似 01-network-manager-all.yaml。 用 nano/ vim 编辑器打开配置文件: sudo nano /etc/netplan/01-network-manager-all.yaml # 替换成你的文件名修改配置文件 network:versi…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
