MySQL 为什么用索引,为什么是 B+树,怎么用索引

MySQL 索引

A database index is a data structure that improves the speed of operations in a table. Indexes can be created using one or more columns, providing the basis for both rapid random lookups and efficient ordering of access to records.

为什么需要索引

根据上面索引的定义,可以知道索引其实是一种数据结构,主要用于提高表中的查询效率,除此之外,索引还是数据库随机高速读取和对记录进行有效排序的基础。

不使用索引情况下数据的读取

除了像 Redis 这样的内存型数据库外,大部分的关系型数据库如 MySQL 等的数据都是直接存储在磁盘上的,而对于从磁盘查找数据来说,需要经历寻道寻址数据传输三个阶段。

  • 寻道:驱动器驱动磁头前后移动到对应的磁道,一般为 5 ~ 14 ms
  • 寻址:磁盘旋转到指定扇区的过程,寻址时间与磁盘转速有关,对于一个 7200 转的磁盘来说,意味着一分钟转 7200 圈,每秒可以转 120 圈,在寻址时,最好情况下磁头正好在正确扇区不需要再次寻址,最差情况下需要转一圈才能到正确扇区,所以寻址的平均时间为 1/120/2=4.17ms1/120/2 = 4.17ms1/120/2=4.17ms
  • 数据传输:数据传输阶段的耗时主要包括两部分,一是磁头从磁盘读取到数据并存储到磁盘缓存所需要的时间,二是从磁盘缓存中读取数据到对应控制器所需的时间;数据传输耗时主要与硬件性能有关,但一般为零点几毫秒。

所以直接从磁盘读取数据的 IO 耗时一般在 10ms 左右,为了避免频繁的磁盘 IO,所以操作系统在读取数据时会以为单位,一次读取目标数据以及和目标数据相邻的一页大小(4K或8K)的数据并放在缓存中,这样下次再读取相邻的数据时就可以直接从缓存中返回了。

MySQL 一次会读四页也就是 16 K

在不使用索引的情况下,如果要查询最后一条数据,就需要从头遍历到尾,
这种情况下,数据库需要读取所有的片才能得到目标数据,大量时间会浪费在磁盘 IO 上,为此,我们需要一种数据结构去记录数据项和磁盘中页的关系,这样在查询某条记录时就可以直接定位到某一页,这样只需要进行一次磁盘IO便可以得到目标数据,可以大大优化查询效率,这种数据结构便是索引。

为什么是 B+ 树

要实现上面的功能,首先可以采用 Hash Table 的方式,将索引键 Hash 之后存储哈希值和键对应的行指针,这样一来,在使用哈希索引查询的时候就可以直接计算出要查询记录的哈希值,然后查询此哈希值对应的行指针,由于每一行所需要的存储空间是固定的,所以得到行指针就相当于定位到了记录对应的页,这时每次查询只需要进行一次磁盘 IO, 可以大大优化查询效率,但哈希索引存在一些问题:

  • 哈希冲突: 只要使用 Hash Table 的数据结构,哈希冲突就是不可避免的,MySQL 中解决冲突的方式是拉链法,即一旦发生冲突就把新的记录以链表的方式链接到原来的记录之后,这样每次查询都需要先遍历这个链表得到一个行指针,再根据行指针查询记录,得到记录后再与要查询的记录作比较,如果得到的不是要查询的记录,要回去取链表中的下一个行指针,再去查询比较,直到得到期望的数据,因此使用哈希索引后的磁盘IO次数取决于冲突的发生率,在存在大量冲突时,哈希索引的查询效率会急速下降。
  • 哈希索引只支持等值查询:由于哈希索引是根据哈希键计算出哈希值,所以它只能在进行等值查询(如 IN, =, <=>)时才能起到优化效率的效果,在进行非等值操作(如 !=, >, <, <>)时起不到任何作用。
  • 组合索引:在使用组合索引时,哈希索引的做法是将所有索引键合并后再做哈希,这就导致对多个字段做组合索引后,再查询其中某一个字段时无法利用索引。
  • 无法根据索引进行有效排序,哈希之后的的值已经丢失了原来的索引键的大小信息,所以无法根据索引进行高效排序

除了使用 Hash Table, 另一个思路是使用排序树,以排序树的结构组织页后,可以将原来查询 O(n)O(n)O(n)的复杂度降低到 lg⁡n\lg nlgno(n)o(n)o(n)的复杂度就意味着每次查询需要进行 nnn 次磁盘IO,使用排序树后虽然不能像哈希表一样达到 O(1)O(1)O(1) 的复杂度,但相比不使用索引可以大大减少磁盘 IO 的次数 。

MySQL 中默认使用 B+ 树构建索引,之所以使用 B+ 树而不是 B 树或二叉排序树的原因在于:

  1. 要选取的树结构必须是稳定的,如果采用二叉排序树,在插入有序序列后,二叉树就会退化为链表,起不到好的优化效果
  2. 根据排序树查询其实是在进行树的深度遍历,而每遍历一个树节点都是一次磁盘IO,所以具体的IO次数取决于树的高度,这就要求树要尽可能矮,也就要求能一个根节点能持有多个子节点。

B+ 树就满足上面两点要求,首先 B+ 树是一棵多路平衡二叉树,其次由于磁盘IO以固定大小的页为单位,所以每次进行磁盘IO能够查询出的数据量是有限制的,这同样意味着树的一个父节点能够持有的子节点数量是有限的,而 B+ 树的数据只存储在叶子节点,中间节点只存储指针,这使得每个中间节点能持有更多的子节点,相比 B 树,B+ 树的高度更低,且每次查询都必须遍历到叶子节点,使得 B+ 树的查询稳定性更高。

虽然上面说 B+ 树的叶子节点存储数据,但具体到 MySQL 对索引的实现上,叶子节点存储的依然不是真正的数据,存储的只是指向真实数据的指针,当然聚簇索引除外,聚簇索引存储数据的顺序和索引顺序是一致的,一张表也只能建立一个聚簇索引,一般用于主键索引。

索引类型

MySQL 索引根据用途不同可以分为以下几种类型:

  1. 普通索引(INDEX)

  2. 唯一索引(UNIQUE INDEX)

  3. 主键索引(PRIMARY KEY)

  4. 组合索引(UNION INDEX)

  5. 全文索引(FULLTEXT ):这是针对大量文本数据的一种特殊所索引,其组织形式也与一般索引不尽相同,主要用于查找文本中的关键字,只能建立在 char、varchar,text 列上, 需要注意的是,直到 MySQL 5.6 InnoDB 引擎才支持了全文索引,在这之前只有 MyISAM 支持, 同时,全文索引一般配合 match against 使用,而不是 where, 关于全文索引的用法,可以参考知乎这篇文章

    值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,然后再用CREATE index创建fulltext索引,要比先为一张表建立fulltext然后再将数据写入的速度快很多。

创建索引

创建索引有三种方式;

  1. 创建表时直接定义

  2. 使用 ALTER 语句修改表结构创建

  3. 直接使用 CREATE TABLE 命令创建:

    CREATE TABLE table_name[col_name data type]
    [unique|fulltext][index|key][index_name](col_name[length])[asc|desc]
    
    • unique|fulltext 为可选参数,分别表示唯一索引、全文索引

    • indexkey 为同义词,两者作用相同,用来指定创建索引

    • col_name 为需要创建索引的字段列,该列必须从数据表中该定义的多个列中选择

    • index_name 指定索引的名称,为可选参数,如果不指定,默认col_name为索引值

    • length 为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度

    • ascdesc 指定升序或降序的索引值存储

删除索引:

  1. 直接删除:

    DROP index_name ON table_name;
    
  2. 通过修改表结构删除

    ALTER TABLE table_name DROP index_name;
    

索引建立的原则

天下没有免费的午餐,索引也并不是万能的,它带来高查询效率的同时也会带来一些问题:

  1. 占用更多的磁盘空间(一般不考虑)
  2. 导致较低的写效率:由于索引需要维持一个庞大的树结构,加上这是一棵排序树,这就会导致某些插入和修改操作会造成树的重建,因此索引带来高查询效率的同时会导致较低的写效率。

所以对一些不应该建立索引的列建立索引后可能导致更差的性能,在考量某一列是否应该建立索引时需要参考一个重要的法则:最左前缀法则,不满足该法则可能导致索引失效进而退化成全表扫描。

最左前缀法则

最左前缀法则是建立联合索引时最重要的法则。

mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配.

如以下的表结构:

CREATE TABLE `left` (`id` int(11) NOT NULL AUTO_INCREMENT,`a` varchar(255) NOT NULL,`b` varchar(255) NOT NULL,`c` varchar(255) NOT NULL,`d` varchar(255) NOT NULL,PRIMARY KEY (`id`),KEY `index1` (`a`,`b`,`c`)
) ENGINE=InnoDB AUTO_INCREMENT=86139 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

我们建立了 a, b, c 的组合索引后:

  1. 在进行等值查询如=IN 时, 可以不考虑顺序,SQL 查询优化器会自动调整语句顺序,如执行下面两条语句的效果是一样的(根据索引长度我们可以推断出对哪几个列使用了索引):

  2. 可以查询建立了聚合索引的某几列,DBS会根据建立索引时的顺序从左开始匹配能够使用索引的列,如执行a = “” AND b = “” 时会对 a 和 b 使用索引,而在执行 a = “” AND c = “" 时则只会对 a 使用索引,而如果只执行 b = “” 时,由于第一个索引 a 就无法匹配到,所以不会使用索引

  3. 最左匹配原则在遇到范围查询:>、<、between、like 时会停止匹配,如执行 a = “” AND b > 10 AND c = “” 时只会对 a 使用索引。

    • 关于 like: like 相比于其他几个要稍微复杂一点,并不是一旦遇见like就会停止匹配,而是通配符如果出现在首位才会停止匹配,如下面的情况:

  4. 对索引列进行运算操作会导致索引失效,原因与 like 的通配符一样,还有需要注意一点,如果索引字段是字符类型,查询时不加引号也会导致索引失效,原因在于MySQL会自动为我们的查询语句转化成字符,这就相当于引入了运算操作:

    SELECT * FROM `left` WHERE a = "" AND b = 1
    -- 将 1 转化为 '1' 的过程引入了运算操作导致索引失效
    
  5. 如果 OR 之后的字段没有使用索引,那么整个索引都将失效。

  6. NOT IN 可能导致的索引失效

为什么要最左匹配

首先要明确的是最左匹配原则适用于联合索引,对于普通索引,不存在匹配的问题,而之所以要严格进行最左匹配,也是由联合索引的数据结构形式决定的:

我们知道 MySQL 默认情况下使用 B+ 树组织索引的数据结构,对于像上文中的联合索引,它的结构是这样的:

相比普通索引的叶子节点,联合索引的叶子节点存储所有关键字的数据,比如建立了a, b, c的索引,那么如上图,每个叶子节点都会存储a, b, c 三个关键字的数据信息,并且会按照建立索引时的顺序排序,但中间节点只会存储第一个关键字的位置指针,当我们执行类似

SELECT * FROM `table` WHERE a = "1" AND b = "2" AND c = "4" 

时,数据库会根据第一个关键字 a 的值 1 定位到某个叶子(图中左边的叶子节点),然后从所有叶子节点的数据里检索出符合第一条规则a = "1" 的数据(图中前六行),然后再从这些数据里检索出符合第二条规则的数据(图中2, 3, 4)行,依次类推直到找到或确认找不到期望数据为止。

而之所以遵循最左匹配原则,也是因为叶子节点的排序方式是按照索引建立时的顺序排序的,也就是 b 只有在 a 相等的情况下才是有序的(如图中第二列整体并不是有序的,但只看 a = 1 前提下的 b 就是有序的了),所以如果跳过 a 去查询 b, 因为无法保证 b 的有序性,只能进行全表扫描。

like 之所以遇到以通配符开头的情况才停止匹配也是由叶子节点的这种数据排序方式决定的,因为 like 字句如果不以通配符开头那他开头的部分是可以利用到排序信息的,如执行:

SELECT * FROM `left` WHERE a = "1" AND b LIKE "2%"

虽然 b 的检索不是等值检索,但我们任然可以根据 like 子句开头的 “2” 快速定位到 2 ~ 4 行,但如果以通配符开头,显然就定位不到了。

索引建立原则

  1. 对经常需要修改的数据不要建立索引,一般数据的读写比为 10:1, 如果低于此,索引可能造成写数据效率低下

  2. 对于重复读高的数据不建议建立索引,如性别,区分度公式为:
    count(distinctcol)count(∗)\frac{count(distinct col)}{count(*)} count()count(distinctcol)

    最好的区分度为 111 ,即所有数据不重复,一般要求区分度高于 0.1

  3. 不建议对不经常查询的列或 “大数据” 建立索引,如 TXT, 二进制信息等。

  4. 建议给主键和外键建立索引,一来主键是唯一的,通过索引检索可以大大提高定位速度,其次为外键建立索引也可以提高表之间连接的速度

  5. 对于经常出现在 WHERE 子句中的或经常按范围查询的列,建议建立索引,由于 MySQL 中使用指针连接了叶子节点,所以对于按范围查询的列,建立索引后可以进一步降低磁盘 IO。

  6. 索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。

  7. 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

索引跳跃式扫描(INDEX SKIP SCAN)

加入我们建立了 a, b, c 顺序的组合索引,但 a 的区分度不高,然后执行了 WHERE b = "" AND ... 就会出现 INDEX SKIP SCAN 的情况, 也就是说 SQL 查询优化器跳过了 a 对后面的列使用了索引,如下面这种情况:

上图中 songs 表结构如下:

+--------+--------------+------+-----+---------+-------+
| Field  | Type         | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id     | bigint(25)   | NO   | PRI | NULL    |       |
| name   | varchar(255) | NO   |     | NULL    |       |
| link   | varchar(200) | NO   |     | NULL    |       |
| singer | int(11)      | YES  |     | NULL    |       |
+--------+--------------+------+-----+---------+-------+

并且为该表建立了 singer, name, link 顺序的组合索引, 但 singer 的区分度约为 0.04, 很低:

mysql> select  COUNT(DISTINCT left(singer,110))/COUNT(*) AS singer, COUNT(DISTINCT left(name,255))/COUNT(*) AS name, COUNT(DISTINCT left(link,200))/COUNT(*) AS link  FROM songs ; 
+--------+--------+--------+
| singer | name   | link   |
+--------+--------+--------+
| 0.0390 | 0.7715 | 1.0000 |
+--------+--------+--------+
1 row in set (25.82 sec)

在这种情况下,由于 singer 的区分度很低,所以全表扫描查询 singer 字段的代价并不是很高,同样对于 singer 来说,使用索引的效果并不明显,但相比之下,后面的 name 和 link 字段的区分度很高,使用索引的效果会非常明显,这时如果由于 “无关紧要” 的 singer 导致后面真正需要索引的 name 和 link 无法使用索引显然得不偿失,因此在 MySQL 8.0 之后加入了 ISS 机制,它允许组合索引在左边的列唯一值较少的情况下跳过左边列对右边列使用索引。

成本优先

索引的出现本就是为了降低查询成本的,但若在某些情况下使用索引反而增加了查询成本,那就不应该使用索引,MySQL 在执行查询前会预估查询成本,然后根据成本决定是否使用索引或使用哪个索引,不使用索引时的查询成本包括两部分:

  1. IO 成本:指的是把数据从磁盘读到内存的成本,前面说到磁盘IO以页为单位,如果每次磁盘IO的成本记为 1, 那么读取一条数据的 IO成本就是:
    Cost(IO)=Data_lengthpage_sizeCost(IO) = \frac{Data\_length}{page\_size} Cost(IO)=page_sizeData_length

  2. CPU 成本:是指将数据读入内存后,还要检测数据是否满足条件和排序等 CPU 操作的成本,一般默认情况下每行的 CPU 成本约为 0.2

而如果表中有索引,在执行查询前,数据库引擎会估算使用索引所需要的成本,具体估算方法参考:xx , 估算出的值可以通过 optimizer_trace 工具查看,如果索引的成本高于全表扫描的成本,那就会放弃索引。

如执行 :

SET optimizer_trace="enabled=on";
SELECT * FROM `left` WHERE a > "1";
SELECT * FROM information_schema.OPTIMIZER_TRACE;
SET optimizer_trace="enabled=off";

后得到使用 index1 索引的成本为 54705

"analyzing_range_alternatives": {"range_scan_alternatives": [{"index": "index1","ranges": ["1 < a"],"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 49977,"cost": 54705,"chosen": false,"cause": "cost"}],"analyzing_roworder_intersect": {"usable": false,"cause": "too_few_roworder_scans"}
}

但全表扫描成本为:


0.2∗Rows+Data_lengthpage_size=0.2∗99954+473497616∗1024=19990.80.2 * Rows + \frac{Data\_length}{page\_size} = 0.2 * 99954 + \frac{4734976}{16 * 1024} = 19990.8 0.2Rows+page_sizeData_length=0.299954+1610244734976=19990.8
显然全表扫描的效率要高于使用索引的效率。

需要注意的是数据库引擎只是只是在估算成本,这个值不一定准确,上面的例子从最左前缀的角度也不应该使用索引,只是为了说明并不是在任何时候数据库引擎都会去使用索引的在涉及到低区分度,Null 值等的时候,引擎会选取一个相对最优的方案。

索引的使用建议

一. 避免索引失效

  1. 谨慎选择组合索引的建立顺序
  2. 涉及非等值操作查询时,谨慎安排查询语句的顺序,避免范围查询导致索引失效
  3. 不要在索引字段上执行计算操作
  4. 匹配字符串时不要依赖 MySQL 的类型转换
  5. 谨慎使用 OR
  6. 谨慎选择 IN, NOT IN, EXISTS

二. 使用索引覆盖

覆盖索引指的是索引字段覆盖了需要查询的所有字段,这时根据索引便可以拿到所有数据而不需要回表查询,反之,如果使用类似 SELECT * 或 索引字段未覆盖期望的所有字段时,未被覆盖的字段就需要回表查询,这便又增加了磁盘 IO 的次数,如果发生了回表查询, EXPLAIN 的描述(Extra)字段会显示 Using index condition 这时我们应该考虑是否需要优化。

三. 有时全表扫描更快

索引不一定能 100% 提高查询效率,使用不当反而会使性能下降

四. 尽量使用复合索引

在每次查询时,数据库只会选择一个最优的索引使用,所以使用复合索引往往优于使用多个单列索引。

总结

  1. 什么是索引:

    • 索引是一种数据结构,用来提高在数据表中的数据查询效率,同时也是随机读和有效排序的基础。
  2. 为什么使用索引:

    • 根本原因在于磁盘速度与内存速度差距甚大,所以我们希望能使用尽可能少的磁盘 IO 次数去拿到想要的数据,因此引入了索引,索引通过哈希表或 B+ 树的方式存储了索引值和数据块的对应关系,使得能够在较低的时间复杂度内拿到数据。
  3. InnoDB 中为什么选择 B+ 树组织索引:

    • 实现索引的数据结构必须能在较低的时间复杂度内找到索引键对应的数据,除了哈希表外,可以选择排序树,同时为了减少磁盘 IO 次数,要求这棵树要尽可能低,要实现自平衡,不能在极端情况下退化为链表,再者,由于操作系统以页为单位进行磁盘 IO,这就意味这不能为了降低树高度无限增加一个树节点的子节点,所以为了保证一个中间节点持有更多子节点而选择 B+ 树而不是 B 树,另外,B+ 树所有数据存储在叶子节点,这样每次查询的时间复杂度都是一致的,可以获得更高的稳定性。
  4. 聚簇索引和非聚簇索引的区别:

    • 聚簇索引在一张表中只能有一个,一般是主键索引,聚簇索引的叶子节点存储的是真实地数据。
    • 非聚簇索引可以建立多个,其叶子节点存储地并不是真实地数据,而是主键值,根据非聚簇索引只能拿到该行记录地主键值,要拿到真实地数据还需要根据聚簇索引去查询
  5. 在什么情况下使用索引:

    • 读操作比例大大高于写操作比例时。
    • 数据区分度高。
    • 主键和外键建议使用。
    • 经常出现在 WHERE 子句中的列。
  6. 如何高效地使用索引:

    • 建立索引时尽量使用组合索引。
    • 不要对大量数据建立索引。
    • 建立组合索引时认真考虑先后顺序。
    • 使用索引时严格遵循最左前缀原则,避免索引失效。
    • 尽量使用索引覆盖,避免 SELECT *

参考

【tutorialspoint】mysql-indexes

【美团技术文章】MySQL索引原理及慢查询优化

【知乎】平衡二叉树、B树、B+树、B*树 理解其中一种你就都明白了

【CSDN】数据库中的索引技术——哈希索引

【360doc】数据库建立索引的原则

【博客园】sql 索引类型

索引跳跃式扫描(INDEX SKIP SCAN)

【腾讯云】 MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!

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

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

相关文章

Servlet 生命周期、工作原理

Servlet 生命周期&#xff1a;Servlet 加载--->实例化--->服务--->销毁。init&#xff08;&#xff09;&#xff1a;在Servlet的生命周期中&#xff0c;仅执行一次init()方法。它是在服务器装入Servlet时执行的&#xff0c;负责初始化Servlet对象。可以配置服务器&…

【Go 并发控制】上下文 context 源码

Context 在 Go 服务中&#xff0c;往往由一个独立的 goroutine 去处理一次请求&#xff0c;但在这个 goroutine 中&#xff0c;可能会开启别的 goroutine 去执行一些具体的事务&#xff0c;如数据库&#xff0c;RPC 等&#xff0c;同时&#xff0c;这一组 goroutine 可能还需要…

iOS开发UI篇—模仿ipad版QQ空间登录界面

一、实现和步骤 1.一般ipad项目在命名的时候可以加一个HD,标明为高清版 2.设置项目的文件结构&#xff0c;分为home和login两个部分 3.登陆界面的设置 &#xff08;1&#xff09;设置第一个控制器和自定义的控制器类&#xff08;登陆&#xff09;关联 &#xff08;2&#xff09…

oracle中scn(系统改变号)

系统scn&#xff1a; select checkpoint_change# from v$database; 文件scn&#xff1a; select name,checkpoint_change# from v$datafile; 结束scn&#xff1a; select name,last_change# from v$datafile; 数据文件头部scn…

三个数相减的平方公式_快收好这份小学数学公式大全!孩子遇到数学难题时肯定用得上...

必背定义、定理公式1.三角形的面积&#xff1d;底高2 公式 S&#xff1d; ah22.正方形的面积&#xff1d;边长边长公式 S&#xff1d; aa3.长方形的面积&#xff1d;长宽公式 S&#xff1d; ab4.平行四边形的面积&#xff1d;底高公式 S&#xff1d; ah5.梯形的面积&#xff1d…

add.attribute向前端传_前端知识-概念篇

1、一次完整的HTTP事务是怎样的一个过程&#xff1f;基本流程&#xff1a;a. 域名解析b. 发起TCP的3次握手c. 建立TCP连接后发起http请求d. 服务器端响应http请求&#xff0c;浏览器得到html代码e. 浏览器解析html代码&#xff0c;并请求html代码中的资源f. 浏览器对页面进行渲…

【数据库】一篇文章搞懂数据库隔离级别那些事(LBCC,MVCC)

MySQL 事务 文章比较长&#xff0c;建议分段阅读 后续如果有改动会在 Junebao.top 之前对事务的了解仅限于知道要么全部执行&#xff0c;要么全部不执行&#xff0c;能背出 ACID 和隔离级别&#xff0c;知其然但不知其所以然&#xff0c;现在觉得非常有必要系统学一下&#xff…

api商品分享源码_SSM框架高并发和商品秒杀项目高并发秒杀API源码免费分享

前言&#xff1a;一个整合SSM框架的高并发和商品秒杀项目,学习目前较流行的Java框架组合实现高并发秒杀API源码获取&#xff1a;关注头条号转发文章之后私信【秒杀】查看源码获取方式&#xff01;项目的来源项目的来源于国内IT公开课平台,质量没的说,很适合学习一些技术的基础,…

Golang 定时任务 github/robfig/cron/v3 使用与源码解析

Cron 源码阅读 robfig/cron/v3 是一个 Golang 的定时任务库&#xff0c;支持 cron 表达式。Cron 的源码真实教科书级别的存在&#xff08;可能是我菜 …&#xff09;,真的把低耦合高内聚体现地淋漓尽致&#xff0c;另外其中涉及的装饰器模式&#xff0c;并发处理等都很值得学习…

修改 cmd 字体为 Consolas

windows 下的 cmd 窗口默认的字体有点难看&#xff0c;长时间使用操作 node.js 有点小疲劳&#xff0c;可以修改注册表替换字体为 Consolas&#xff0c;并且可以全屏 cmd 窗口&#xff0c;代码如下&#xff1a; Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Conso…

关于 HTTP 的一切(HTTP/1.1,HTTP/2,HTTP/3,HTTPS, CORS, 缓存 ,无状态)

HTTP 为什么会出现 HTTP 协议&#xff0c;从 HTTP1.0 到 HTTP3 经历了什么&#xff1f;HTTPS 又是怎么回事&#xff1f; HTTP 是一种用于获取类似于 HTML 这样的资源的 应用层通信协议&#xff0c; 他是万维网的基础&#xff0c;是一种 CS 架构的协议&#xff0c;通常来说&…

AS 2.0新功能 Instant Run

Instant Run上手作为一个Android开发者&#xff0c;很多的时候我们需要花大量的时间在bulid&#xff0c;运行到真机&#xff08;虚拟机&#xff09;上&#xff0c;对于ios上的Playground羡慕不已&#xff0c;这种情况将在Android Studio 2.0有了很大改善&#xff0c;使用instan…

MySQL InnoDB 是如何存储数据的

InnoDB 是怎么存储数据的 本文是《MySQL 是怎样运行的 —— 从根儿上理解 MySQL》读书总结&#xff0c;强烈推荐这本书&#xff1b; CSDN 不能显示 SVG&#xff0c;可能有图片加载不出来&#xff0c;可以到 我的博客 上看。 数据目录 众所周之&#xff0c;MySQL 的数据是存储在…

WebSocket实战之————GatewayWorker使用笔记例子

参考文档&#xff1a;http://www.workerman.net/gatewaydoc/ 目录结构 ├── Applications // 这里是所有开发者应用项目 │ └── YourApp // 其中一个项目目录&#xff0c;目录名可以自定义 │ ├── Events.php // 开发者只需要关注这个文件 │ ├── st…

[转]关于凸优化的一些简单概念

没有系统学过数学优化&#xff0c;但是机器学习中又常用到这些工具和技巧&#xff0c;机器学习中最常见的优化当属凸优化了&#xff0c;这些可以参考Ng的教学资料&#xff1a;http://cs229.stanford.edu/section/cs229-cvxopt.pdf&#xff0c;从中我们可以大致了解到一些凸优化…

centos7部署两个mysql_一文掌握mysql实用工具--pt-online-schema-change、innotop部署

概述因为OSC和innotop这两个需要的依赖包比较接近&#xff0c;所以这次就写一起了&#xff0c;下面介绍下完整的部署教程&#xff0c;以下基于centos7操作系统。官网文档&#xff1a;http://dev.mysql.com/doc/refman/5.7/en/innodb-create-index-overview.htmlOSC&#xff1a;…

python面试题目

问题一&#xff1a;以下的代码的输出将是什么? 说出你的答案并解释。 1234567891011121314class Parent(object):x 1class Child1(Parent):passclass Child2(Parent):passprint Parent.x, Child1.x, Child2.xChild1.x 2print Parent.x, Child1.x, Child2.xParent.x 3print …

修改页面后获得flag_互动征集丨是时候为2021立flag了

2020马上就要过去了今年的flag各位小伙伴实现了多少&#xff1f;翻出了生灰的flag擦擦说不定2021还能接着用哦2020年就要过去了还记得你在年初立下的那些Flag吗&#xff1f;减肥“明天我就开始减肥&#xff01;”是大部分人在大部分时候都挂在嘴边的一句话疫情宅家不仅没减成还…

为ESXI 添加ISCSI存储设备 Linux服务器系统

为ESXI 添加ISCSI存储设备 Linux系统本文使用的LINUX 6系统上一块硬盘制作的ISCSI存储设备其IP地址为&#xff1a;192.168.26.218:在系统上直接输入&#xff1a;yum -y install scsi-target-utils 命令 安装 iscsi分区设置我们将SDD这块硬盘的SDD1作为iscsi存储设备编辑ISCSI配…

出栈顺序 与 卡特兰数(Catalan)的关系

一&#xff0c;问题描述 给定一个以字符串形式表示的入栈序列&#xff0c;请求出一共有多少种可能的出栈顺序&#xff1f;如何输出所有可能的出栈序列&#xff1f; 比如入栈序列为&#xff1a;1 2 3 &#xff0c;则出栈序列一共有五种&#xff0c;分别如下&#xff1a;1 2 3、…