InnoDB关键特性

插入缓冲(Insert Buffer)

问题:

  在InnoDB插入的时候,由于记录通常都是按照插入顺序,也就是主键的顺序进行插入的,因此,插入聚集索引是顺序的,不需要随机IO。但是对于非聚集的索引,则由于B+树的特性需要随机IO

解决:

  插入缓冲就是为了解决这个问题。对于非聚集且非唯一的索引,他们的插入先不进行实际的插入,而是先缓存下来,再在某些情况下或定期的真正插入。

如目标页不在内存中,且当前将其读到内存中,就可以先将 buffer 里面的数据应用,再进行操作

该非聚集索引不能是唯一的,这是因为要确保唯一性,就要实际的去随机IO来保证没有重复,这样的话随机IO就已经发生了,无法通过插入缓存来避免。

缺陷:

  在写密集的情况下,插入缓冲会占用过多的innodb_buffer_poll,默认最多能占用一半的内存。

Change Buffer

对于DML操作都能进行缓存

该特性适用于读少写多的场景,因为写后读会立刻 merge

两次写(Double Write)

问题:

  数据库在宕机时,某个正在写的页会丢失,即使要用 redo log 恢复,也需要先用页的副本来恢复。

解决:

  在对数据库的脏页进行刷新时,会先写到内存中的double write buffer,之后会通过double write buffer分两次顺序写入到共享表(在物理磁盘)中。最后再将共享表中的页写入到各个表文件中。

脏页

在内存已经被修改的 Page,还没有刷新到磁盘,但是它会达到最终一致

脏数据

一个事务读到的另一个事务未提交的数据

此时,如果再宕机,InnoDB可以在共享表中找到页的副本,将其复制到对应的表空间。

不过,在从服务器上,可以关闭这个功能来提升性能。

自适应哈希索引(Adaptive Hash Index)

问题:

  B+树的查找次数取决于其高度,生产中会在3~4层。

解决:

  InnoDB能监控索引的查询,根据监控的结果,来自动为某些热点项建立哈希索引,以提升查询效率。

异步I/O(Asynchronous IO)

问题:

  同步IO,即每一次IO操作都需要等待IO结束才能继续。

解决:

  异步IO可以一次将所有IO请求发送完,等待所有结果返回。同时还可以合并要访问的页,来避免同时多次访问一页。

刷新邻接页(Flush Neighbor Page)

在刷新一个脏页时,InnoDB可以顺便将其同区的脏页一起刷入,来合并IO操作。

在 MySQL 8.0 被设置为0,这是因为在 SSD 中作用不大

文件

参数文件

通过 mysql --help | grep my.cnf 来找到文件位置

show variables 找到参数

日志文件

  • 错误日志(error log)

    位置:show variables like 'log_error'

  • 二进制日志(binlog)

    对数据库的所有更改操作的记录

    数据恢复、数据复制

  • 慢查询日志(slow query log)

    阈值为 long_query_time 的值(ms)

    开关为 log_slow_queries

    log_queries_not_using_indexes :无索引同样记录

    log_throttle_queries_not_using_indexes :每分钟允许记录的无索引查询

  • 查询日志

  • 中续日志

  • 事务日志

socket 文件

使用Unix套接字后再本地连接的文件

pid 文件

MySQL示例运行后的pid写入

MySQL表结构文件

.frm 结尾的文件,用来存储表的结构

存储引擎文件

redo log

至少有一个 redo log 组,每个组下至少有2个 redo log file,可以设置多个镜像日志组在不同硬盘上

但 redo log buffer 只有一个

与 bin log 的区别是,bin log 会记录与MYSQL有关的记录,而 redo log 只会记录与存储引擎本身的事务,同时,它记录的是每个页的更改的物理情况。

同时 bin log 只在事务提交前进行提交,而 redo log 是任何情况下都写入。

表空间是最高层,所有的数据都放在表空间中

表空间由各个段组成,常见有数据段、索引段、回滚段等。InnoDB是索引结构的,数据段为B+树的叶子节点,索引段则为它的非索引节点

区是由连续的页所组成的空间。任何情况下,区都为1MB。InnoDB一次申请4-5个区。默认情况一个页为16kb

页是InnoDB磁盘管理的最小单位,可以设置为4K、8K、16K。

常见的页类型
  • 数据页(B-tree Node)

  • undo页(undo Log Page)

  • 系统页(System Page)

  • 事务数据页(Transcaction system Page)

  • 插入缓冲位图页(Insert Buffer Bitmap)

  • 插入缓冲空闲列表页(Insert Buffer Free List)

  • 未压缩的二进制大对象页(Uncompressed BLOB Page)

  • 压缩的二进制大对象(compressed BLOB Page)

InnoDB是面向列的,就是说是按行来存放的。

Compact 行记录格式

变长字段长度列表-NULL标志位-记录头信息-列1数据-列2数据-....

  1. 小于255,用1字节表示
  2. 大于255,用2字节表示

不会超过2个字节,因为varchar的最大长度为65535

varchar最多长度为65535,实际上的长度会低于这个长度,并且这个长度是一行的长度。

InnoDB的页为16k,并不能容下65532字节,所以发生行溢出的时候,数据会存放在 Uncompress BLOB页中。此时在原地址中会保存他的前768字节的前缀数据,然后是指向溢出页的地址。

对于char,由于多字节的字符编码,CHAR不是固定长度的字符串,所以也会将它视为变长,没有占满的会填充0x20

Barracuda拥有两种新的行记录格式:Compressed和Dynamic

这两种会对Blob进行完全的溢出,就是说只存指针,同时会用zlib进行压缩

InnoDB页结构
  • File Header(文件头)

  • Page Header(页头)

  • Infimun 和 Supremum Records

    两个虚拟行记录,用来确定记录的边界。

  • User Records(用户记录,就是行记录)

  • Free Space(空闲空间)

    一条记录被删除后,会被放到空闲空间

  • Page Directory(页目录)

  • File Trailer(文件结尾信息)

    确认页完整写入磁盘

分区

垂直拆分

  将字段进行拆分,将主要热门的数据拆分为单表,其余设计为次要表

产生问题:会引起本来不必要 JOIN 操作、事务处理复杂

水平拆分

  利用函数分片,如hash,ID范围\时间,映射表

产生问题:分布式事务、关联的表不在同一库(跨节点 JOIN)、ID要保证唯一性

Mysql 原生只支持水平分区,不支持垂直分区

支持的分区类型

  • range

    连续区间、通常用于按时间列的分区,因为这样可以触发分区修剪

用时间分区会导致写入操作集中在一个分区,热点倾斜问题。

  • list

    离散的区间

  • hash

    用户自定义的表达式,也可以直接提供列名

  • key

    使用提供的哈希函数,与hash的区别在于,这是使用的MySQL内部的函数

散列能解决热点倾斜,但会失去区间查询特性

分区列需要是唯一索引的一部分,没有主键或唯一索引则可以加入任意的列进行分区

子分区:在分区的基础上再分区,可在在RANGE和LIST的分区上进行Hash或KEY的子分区

NULL值在range上视为最小值,LIST下要显示指定,hash和key会直接视为0

  • 对于引擎层,会生成多个表;对于 Server 层,只有一个表
  • 所有分区会共用一个 MDL 锁

二级索引

  • 基于文档

    每个分区维护自己的数据的索引

  • 基于词条

    全局索引,并且索引拆分

对于OLAP,分区可以很好的提升性能,这是因为要频繁的查询

索引

类型

B+树索引、全文索引、hash索引、R-Tree索引

B+树索引不能直接找到具体行,只能查到其所在,然后将其读到内存再进行二分查找,才能找到对应行

数据库中的B+索引可以分为聚集索引辅助索引,索引页指向的是数据页的偏移量

优点
  1. 大大减少了服务器需要扫描的数据量
  2. 帮助服务器避免排序和临时表
  3. 将随机IO变为顺序IO
缺点
  1. 索引需要占用额外的内存
  2. 降低表的DML的操作的速度
  3. 在巨大数据量下工作不是很好,这种情况下需要分区
注意
  • 索引的列必须是独立的列
  • 我们可以通过计算 选择性 建立前缀索引,缺点是分布可能不均和无法使用order by和group by,同时无法作用索引覆盖

选择性

不重复的索引值和记录总数的比值

  • 将选择性最高的列放在最前面
  • 范围查询停止匹配

基数(Cardinality)

  查询优化器会根据索引中的 Cardinality 来判断是否使用这个索引,但这个值不是实时更新的,所以可以使用analyze table命令来重新分析。

更新策略:

  1. 1/16 的数据已经发生了变化
  2. stat_modified_counter(变化的次数) > 2 000 000 000

计算过程:

  1. 取得叶子节点数量,为A
  2. 随机取索引的8个叶子节点,统计每个页不同记录的个数,记为 \(P1\) 、\(P2\) \(...\) \(P8\)
  3. $Cardinality=(P1+P2+...+P8) * A/8 $

FIC:快速创建辅助索引,创建时会加上S锁

SHARE:将在索引创建中的执行数据加入到日志里,在创建后使用其进行重做

数据更新频繁可能导致基数不准,可以通过 analyze table t 来重新统计索引信息

HASH索引

特性:

  • 只存储指针,不能索引覆盖
  • 不是顺序存储,不能帮助排序,不能范围查询
  • 不存在最左匹配原则

联合索引

  本质也是B+树,只是其键值的数量大于等于2,且从左到右建立索引

InnoDB对同时有联合索引和单个索引的选择

  直接查询:会选择单个索引,这是因为它的叶子节点包含单个键值。所以一个页可以存放更多的记录。

  查询选定目标的最近记录:会选择联合索引,因为第二个字段在联合索引中已经排序好了

前缀索引

 ?字符串索引的一种方法,可以通过统计每增加一位带来的区分度,来选择前缀长度。同时可以使用倒叙存储和 Hash 字段来优化。

 ?缺点在于,不能索引覆盖和范围查询

索引覆盖

  直接从辅助索引中得到查询的数据,不需要回表查询,在辅助索引上具有主键和辅助索引上的值。

  索引覆盖被使用后会出现 using index

索引合并

  用多个单列索引来定位引用的值,即将多个不同的索引查询拆分并使用union

前缀压缩

  MyISAM可以对具有相同前缀的字符串只存储一次

不走索引的情况

  1. 索引列参与了计算或函数
  2. 空值
  3. 复合索引(a-b-c),只用到了a和c。此时可以通过枚举b值的技巧走索引

force index 可以强制选择索引

MRR(Multi-Range Read)

  减少磁盘的随机访问。原理是在获取所有的辅助索引的键值后,通过主键进行排序。

ICP(Index Condition Pushdown)

  在取出索引时判断where,这个需要判断的条件能够被索引覆盖的时候才生效

自适应哈希索引

发现二级索引频繁的访问后会被生成到Hash索引里面去

全文索引

倒排索引,在辅助表中存储了单词与单词在一个或多个文档中位置之间的映射

inverted file index

  形式为 {单词, 所在文档的ID}

full inverted index

  形式为 {单词,(单词所在文档ID,在文档的具体位置)}

碎片

  • 行碎片

数据行被存储在多个地方的多个片段

  • 行间碎片

在逻辑上顺序的页或行,在磁盘上不是顺序存储的

  • 剩余空间碎片

数据页中有大量的空余空间

通过 optimize table 重新整理数据

SQL 优化思路

字段优化

  • 数据范围尽量小且简单

  • 字段设计不设置null

    原因:

    1. 负向查询不能命中索引
    2. 预料之外的结果集
    3. 额外维护null造成的其他工作量

    InnoDB对null用额外标志位进行了处理,可用于存储稀疏数据

  • char 和 varchar 在多字节字符集下的实际存储没有区别

  • 避免使用bit

  • 防止过多的列

语句优化

  • 防止大量关联

  • 不使用 select *

  • 多个简单查询 > 一个复杂查询

    • 删除大量数据时,一次语句会锁很多行,占据日志,要进行拆分
    • 分解关联查询
    1. 提高缓存命中率
    2. 减少锁的竞争
    3. 应用层关联,更易进行拆分

JOIN 优化

  • 应该让小表去做驱动表
  • 被驱动表上应该走索引
  • 如果 join 较慢,可以调大 join_buffer_size

海量数据量下的优化

  1. 分页

    在MySQL使用limit分页时,会先获取所有的数据,再根据limit来丢弃,这样在大数据量下会出现效率低下问题。

  • 延迟关联
select uid from user inner join (
select id,uid from user
where x.set = '男'
order by name
limit 1000000,10
) as x using(id,uid)

  通过索引覆盖先获取id,再通过id获取详细信息,这样可以减少扫描时需要丢掉的行。

  • 子查询分页
select * from user where id >= (
select id from user
order by id
limit 1000000,1
) limit 10

  原理和延迟关联接近,先通过只查id来减少需要丢掉的行,再通过获得的id来获得需要的下十列。

  • 使用前一次查询的id
select * from user
where id > 999990
order by id
limit 10

 ?通过上一次获得的id,来直接作用于下一页,这样减少了重复的查询。

一次查询的过程

graph TB
A(客户端) -->
|SQL| B(查询缓存) -->
C(解析器) -->
|解析树| D(预处理器) -->
|解析树| E(查询优化器) -->
|查询执行计划| F(查询执行引擎) -->
G(存储引擎)
  1. 查询缓存(MySQL 8.0 移除)

通过Hash查找有没有匹配的语句,有则直接返回

  1. 解析器

语法分析,词法分析,生成解析树

  1. 预处理器

检查解析树是否合法(表名列名是否存在等),鉴权

  1. 查询优化
静态优化

  对where的条件装换为另一种形式等

动态优化

  对于where的取值和索引中的行数等

估算查询计划的成本

  通过成本选择查询计划,可以通过 show status like 'Last_query_cost' 查看优化器估计需要访问多少的页

  1. 查询执行引擎

通过存储引擎提供的接口来执行查询计划,将结果返回并加入缓存

latch

  轻量级的锁,锁定时间短,InnoDB中分为mutex(互斥量),rwlock(读写锁),无死锁机制。

lock

  对象是事务,用来锁对象,在commit或rollback后释放,有死锁机制。

行级锁

  共享锁(S Lock),排他锁(X Lock)

意向锁

  当一个锁打算获取表锁的时候,需要逐一检查每一行是否有其他锁,但如果有了意向锁,在表上就能知道有其他锁阻塞(快速失败)。

一致性非锁定读

  通过多版本并发控制(MVCC)实现的功能,当要读取的数据处于DELETE或UPDATE状态时,可以直接读取其历史快照。

在读提交(READ COMMITED)和可重复读(REPEATABLE READ)中的锁定是不一样的,在前者中,会读取被锁定的最新数据,而后者会读取事务开始时的行数据

一致性锁定读

FOR UPDATE 施加 \(\text X\) 锁,LOCK IN SHARE MODE 施加 \(\text S\) 锁,这个模式只有在选择的情况下生效。

插入类型

  • insert-like,所有的插入语句
  • simple inserts,在插入前能确定插入行数的语句
  • bulk inserts,插入前不能确定得到插入行数的语句
  • mixed-mode inserts,一部分是自增长,一部分未知

自增长的方法

  • 通过表级别AUTO-INC的锁(如果rollback就会浪费)
  • 对于simple inserts使用互斥量(mutex)批量获取ID,获取到足够的ID就会释放锁(间隙更多了),对于bluk inserts还是使用表锁。mutex需要等待表锁。
  • 所有语句对同一值进行CAS

InnoDB 计数器在8.0前存在内存中,8.0后保存到 redo log 中

MyISAM 的自增值保存在内存中

外键

mysql会自动给外键加索引

锁算法

  • Record Lock:单个行上的锁

    总是去锁索引,没有索引则会用隐式的主键去锁定

  • Gap Lock:间隙锁,锁范围不锁本身

  • Next-Key Lock:上面两锁的集合,锁范围和本身

    对于行的查询,都是使用该算法

    具有唯一性时,会降级为Record Lock

例:对于1,3,6,进行3的查询,锁的范围会是(1,3),[3,6)

如果不这样做,会导致幻读问题

同一事务下,连续读取两次某个范围的记录,读取的结果不一样

例:

select * from t where id > 2

此时记录有1,2,5,查询的结果应该是5

现在 insert into t values(6)

由于存在next-key lock,会锁住(2,+inf),所以无法插入

事务

  • 扁平事务

  • 带有保存点的扁平事务

  • 链事务

    和上一次同的是,会释放当前事务的锁,且只能回滚到最近一个事务

  • 嵌套事务

  • 分布式事务

ACID 的 D 由 redo log 和 undo log 实现(事务日志)

redo log

由 redo log buffer 和redo log file 组成

保证事务的持久性,基本是顺序写,默认是在事务提交前先写入到磁盘(日志先行),事务提交后才会缓慢刷新回磁盘。也可以通过设定来定时写入和手动写入,在大数据量插入下,这样效果更好,但是会丧失ACID的D。

InnoDB中,重做日志是以512字节存储的

写入磁盘的时机:

  • 后台线程每秒都将 buffer write 并 fsync
  • 占用空间到达 buffer_size 一半的时候,只 write 不 fsync
  • 并行的事务提交时,顺带将 buffer 持久化
组提交

每个日志具有逻辑序列号,在并行事务提交的时候其他事务一起刷入磁盘,而 fsync 调用的次数越少,节约次数越好

binlog

用于 PIT 恢复和主从复制,和重做日志的区别在于,这个是MySQL的上层生成的,记录的是各种SQL语句。

其 Cache 由每个线程维护。

只有在事务提交的时候,才会将其刷新回磁盘。可以通过 sync_binlog 来控制 write 和 fsync 的时机

0:只 write,不 fsync

1:提交事务时都 fsync

N:每次都 write,N 次后才 fsync

每次事务都带有两次刷盘:

? redo log prepare(write) -> binglog(write) -> redo log prepare(fsync) -> binlog(fsynnc) -> red log commit(write)

undo log

记录数据被修改前的日志,帮助事务回滚和MVCC需要用的历史快照的功能

MVCC

通过对数据做多版本管理,来实现了提交读和可重复性读,并且部分解决了幻读

快照读

基于undo log历史版本的读取,不需加锁,配合MVCC能解决幻读

当前读

总是读数据库最新的数据,任何操作都需要加锁(读锁或写锁),需要配合 Next-key Locks 才能解决幻读

InnoDB在select时会使用快照读(for update 除外),update、insert、delete会使用当前读

使用
  1. 获取事务编号
  2. 把修改前的数据存储到undo log
  3. 修改数据
  4. 将修改后的事务版本号改成当前事务版本号,将undo log地址放入
Read View

这在SQL语句执行前会获得,结构为

  • trx_ids:未提交事务的版本号集合
  • low_limit_id:当前最大版本号+1
  • up_limit_id:未提交事务的最小版本号
  • creator_trx_id:当前事务版本号

结果集 在每一行匹配前判断,若

  • 该行 事务版本 < up_limit_id,说明是在Read View创建前修改的,故直接显示
  • 该行 事务版本 >= low_limit_id,说明最后修改为Read View之后,故不显示
  • 该行 up_limit_id < 事务版本 < low_limit_id,说明该记录在Read View创建之时,被另一个事务修改,则若
    • 事务版本 不在trx_ids中,说明修改它的事务已经提交,可以显示
    • 事务版本 在trx_ids中,且为creator_trx_id,说明修改它的事务是它自己,可以显示
    • 事务版本 在trx_ids中,但不为creator_trx_id,说明修改它的事务仍未提交,不能显示

以上判断中,若判定为不显示,则会到undo日志,对每一条记录重复以上判断,直到满足条件,或日志到达尾部。

MVCC可以在读提交和可重复读中运行

读提交中(read commit)中,每一次查询都会获取一个新的read view,这会出现不可重复读

可重复读(read repeated)中,一次事务只会获取一个read view

故从这可以看出在InnoDB中,可重复读的效率比读提交的效率要高

垃圾回收

用户删除的数据只是将其进行了标记,过期的undo log等需要等待后台的Purge线程回收

分布式事务

2PC

两阶段提交

  1. 协调者向所有节点发送准备请求
  2. 协调者向所有节点发送提交请求

XA事务

RM(资源管理器):提供访问事务资源的方法

TM(事务管理器):协调各个事务

AP(应用程序):定义事务的边界,全局事务中的操作

备份与恢复

热备份:数据库运行时直接备份

ibbackup

冷备份:数据库停止下复制相关物理文件

温备份:会对数据库运行有影响的备份

逻辑备份:备份出可读的文件,一般是SQL语句

mysqldump、select ... into outfile

裸文件备份:复制数据库的物理文件

完全备份:完整的备份

增量备份:对于上次备份的基础进行备份

日志备份:对二进制日志的备份

复制

主从复制

过程:

  1. 指定一个节点为主节点,写请求时会发送到这个节点
  2. 其余节点为从节点,从主节点获取日志,然后写入
  3. 读请求可以打到主节点或从节点

同步复制:主节点等待从节点确认更改才返回成功

异步复制:主节点自己成功后直接返回

半同步:部分同步,部分异步,同步节点挂时,对异步选举

从节点失效:追赶式恢复

主节点失效:确认失效、选举新节点、配置新节点

产生问题:

  • 读自己的写:从节点还未获取修改就读(写后读一致性)
  • 单调读:不同从节点数据不同问题(单调读一致性)
  • 前缀一致性:写入顺序混乱(分区造成的问题)

多主节点复制

写冲突:对同一块位置进行写

  1. 避免冲突:分位置选择数据中心
  2. 收敛于一致状态:应用层处理冲突

无主节点复制

节点失效重启后的数据恢复

  1. 读修复

    读取多副本时,检测不同并回写

  2. 反熵过程

    后台不断查找差异并副本复制

MySQL为基于行的逻辑日志复制

(1) 主服务器将数据更改记录到binlog

(2) 将binlog复制到自己的relay log

(3) 重放relay log,达到数据一致性

参考资料

  1. 《高性能MySQL(第3版)》
  2. 《MySQL技术内幕:InnoDB存储引擎(第2版)》
  3. MySQL实战45讲

学习手册 | MySQL篇 · 其一的更多相关文章

  1. 数据库MySQL学习笔记高级篇

    数据库MySQL学习笔记高级篇 写在前面 学习链接:数据库 MySQL 视频教程全集 1. mysql的架构介绍 mysql简介 概述 高级Mysql 完整的mysql优化需要很深的功底,大公司甚至有 ...

  2. MySQL 总结篇 [在Oracle基础上学习的MySQL]

    一.学习环境 MySQL 5.7社区版 Navicat for MySQL 百度网盘下载链接:https://pan.baidu.com/s/1yGnznwoZ8CaMgrCsDBhKAQ 二.MyS ...

  3. (转) 坚持完成这套学习手册,你就可以去 Google 面试了

      坚持完成这套学习手册,你就可以去 Google 面试了 系统 指针 value Google 面试 阅读6138    本文为掘金投稿,译文出自:掘金翻译计划 原文地址:Google Interv ...

  4. PHP学习笔记 - 进阶篇(11)

    PHP学习笔记 - 进阶篇(11) 数据库操作 PHP支持哪些数据库 PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Syba ...

  5. PHP学习笔记 - 进阶篇(2)

    PHP学习笔记 - 进阶篇(2) 函数 1.自定义函数 PHP内置了超过1000个函数,因此函数使得PHP成为一门非常强大的语言.大多数时候我们使用系统的内置函数就可以满足需求,但是自定义函数通过将一 ...

  6. 《Python学习手册》读书笔记

    之前为了编写一个svm分词的程序而简单学了下Python,觉得Python很好用,想深入并系统学习一下,了解一些机制,因此开始阅读<Python学习手册(第三版)>.如果只是想快速入门,我 ...

  7. Python学习笔记进阶篇——总览

    Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(Socket编程进阶&多线程.多进程) Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(异常处理) Pyth ...

  8. PostgreSQL学习手册

    事实上之前有很长一段时间都在纠结是否有必要好好学习它,但是始终都没有一个很好的理由说服自己.甚至是直到这个项目最终决定选用PostgreSQL 时,我都没有真正意识到学习它的价值,当时只是想反正和其它 ...

  9. 前端学习数据库MYSQL

    这篇文章主要写了 1.数据库MYSQL 2.基本上会遇到的所有SQL语句 数据库可视化软件------Navicat 数据库里边存放的是表,表与表之间是有关联的,而且可以对表进行相关操作(增,删,改, ...

随机推荐

  1. 细谈布隆过滤器及Redis实现

    ​ 何为布隆过滤器? 本质上是一种数据结构,是1970年由布隆提出的.它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数).可以用于检索一个元素是否在一个集合中. 数据结构: 布隆过 ...

  2. 【第二篇】- Maven 环境配置之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 环境配置 Maven 是一个基于 Java 的工具,所以要做的第一件事情就是安装 JDK. 如果你还未安装 JDK,可以参考我们的 Java 开发环境配置. 系统要求 项目 要求 JDK ...

  3. RocketMQ详解(一)原理概览

    专题目录 RocketMQ详解(一)原理概览 RocketMQ详解(二)安装使用详解 RocketMQ详解(三)启动运行原理 RocketMQ详解(四)核心设计原理 RocketMQ详解(五)总结提高 ...

  4. HCNP Routing&Switching之IS-IS路由聚合和认证

    前文我们了解了IS-IS路由渗透和开销相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15302382.html:今天我们来聊一聊IS-IS路由聚合和认 ...

  5. POJ1321——棋盘问题

    http://poj.org/problem?id=1321 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解 ...

  6. python三种导入模块的方法

    做为python初学者,有时候搞不清楚导入模块的作用. 直接导入模块 通常模块为一个文件,直接使用import来导入就好了.可以作为module的文件类型有".py"." ...

  7. python学习笔记(三)-列表&字典

    列表: 一.列表操作"""Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素.比如,列出班里所有同学的名字,就可以用一 ...

  8. 关于Python中的深浅拷贝

    之前一直认为浅拷贝是拷贝内容的第一层,但是不开辟内存,只是增加新的指向原来的内容:深拷贝是拷贝是拷贝每一层并开辟内存. 其实这个是不严谨的不正确的. 从以上可以看出,浅拷贝中当时可变类型的时候,内存是 ...

  9. P4240-毒瘤之神的考验【莫比乌斯反演,平衡规划】

    正题 题目链接:https://www.luogu.com.cn/problem/P4240 题目大意 \(Q\)组数据给出\(n,m\)求 \[\sum_{i=1}^n\sum_{j=1}^m\va ...

  10. Go语言之函数

    函数就是一块执行特定任务的代码,在输入源的基础上通过一些算法生成预期的输出. 一.函数的声明 Go 语言中的函数声明语法如下: func 函数名(参数名 类型,参数名 类型)(返回值1类型,返回值2类 ...