(三)、MySQL索引

news2025/1/14 0:43:15

一、索引基础

        索引是存储引擎用于快速找到记录的一种数据结构。(可以理解为一本书的目录)。
        例子:where id=1 如果在id列上建有索引,则MySQL将使用该索引找到id为1的行,也就是说,MySQL先在索引上按值进行查找,然后返回所有包含该值的数据行。
        索引可以包含一个或多个列的值。如果索引包含多个列,那么列的顺序也十分重要,因为MySQL只能高效地使用索引的最左前缀列。创建一个包含两列的索引,和创建两个只包含一列的索引是大不相同的。

1、索引的类型

        索引有很多种类型,可以为不同的场景提供更好的性能。在MySQL中,索引是在存储引擎层而不是服务器层实现的。所以并没有统一的索引标准:不同存储引擎的索引的工作方式不一样,也不是所有的存储引擎都支持所有类型的索引。即使多个存储引擎支持同一种类型的索引,其底层的实现也可能不相同。

        B-Tree
       
存储引擎以不同的方式使用B-Tree索引,性能也各有不同。MyISAM使用前缀压缩技术使得索引更小,但InnoDB则按照原数据格式进行存储。再如MyISAM索引通过数据的物理位置引用被索引行,而InnoDB则根据主键引用被索引的行。InnoDB使用的是B+Tree。
        B-Tree工作方式:在访问数据时,存储引擎不再进行全表扫描,而是从索引的根节点开始进行搜索。根节点的槽中存放了子节点的指针,存储引擎根据这些指针向下查找。通过比较节点页的值和要查找的值可以找到合适的指针进入下层子节点,这些指针实际上定义了子节点页中值的上下限。


        B-Tree的查询类型。全键值、键值范围、键前缀。
        解释中的例子:表:last_name、first_name、brithy_day。并创建组合索引key(last_name、first_name、brithy_day)。下列为组合索引图解,每个节点的第一层到第三层分别对应last_name、first_name、brithy_day


        索引限制

  • 如果不是按照索引的最左列开始查找,则无法使用索引。上述例子中不能直接在条件中查找first_name或brithy_day,因为此类查找跳过了最左边的索引last_name。
  • 不能跳过索引中的列。条件查询last_name和brithy_day,跳过了first_name,则生效的索引列只有last_name。
  • 如果条件中存在范围查询,则范围查询后的列索引失效。条件查询“last_name=abc  and first_name like "%bb% " and brithy_day ="2020-01-11" ”,索引生效的列只有last_name和first_name

哈希索引

        哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的值,并且不同键值的行计算出来的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。
        在MySQL中只有Memory引擎支持哈希索引。这也是Memory引擎表的默认索引类型,同时它也支持B-Tree索引。Memory引擎如果存在多个列的哈希值相同,索引会以链表的方式存放多个记录指针到同一个哈希条目中。
        哈希索引的数据结构有两列:槽、值,槽为对应索引列计算出的哈希值,值为数据所在行的指针。
        MySQL中查询带有哈希索引列时,首先会读对传入的条件值进行哈希计算得到一个哈希值,然后去匹配哈希索引中所在的槽,并得到值(存储的是指向所在行的指针)。
        哈希索引的限制:

  • 哈希索引只包含哈希值和行指针,而不是存储字段的值。不过访问内存中行速度快,并不影响性能
  • 哈希索引数据并不是按照索引值的顺序存储,所以不能用于排序。
  • 哈希索引不支持匹配查询。因为哈希值是用列的全部内容计算得出的值。
  • 哈希索引只支持等值匹配(=、in、<>...),不支持范围查询(>、<...)
  • 哈希索引访问速度快,除非出现哈希冲突(不同内容计算出相同的哈希值),当出现哈希冲突时,存储引擎必须便利链表中的所有元素与之匹配。
  • 哈希冲突多的话,维护操作的代价较高。当建立哈希索引的列中出现很多哈希冲突,就会导致此哈希值链表很长,比较对应的值就会便利此链表。

        InnoDB引擎中有一个特殊的功能叫做“自适应哈希索引”。当InnoDB注意到某些索引值被使用的非常频繁时,它会在内存中基于B-Tree索引之上在创建一个Hash索引,这样B-Tree就有了哈希索引的一些优点。

        伪哈希索引。对于URL这类较长的字符,使用B-Tree会导致存储的内容比较大。可以针对存储URL字段的列在创建一列,用于保存URL进行哈希计算的值,在进行where查询时可以直接使用这个字段去匹配条件值的Hash值。建议使用CRC32做哈希计算,SHA1和MD5计算的哈希值较长,会浪费大量空间。同时也可以使用插件来引入FNV64函数,相较于CRC32,速度快,且有更长的哈希值,减少哈希冲突。

二、索引的优点

        1、减少服务器需要扫描的数据量
        2、帮助服务器避免排序和临时表
        3、可以将随机I/O变为顺序I/O

        索引对于中大型表比较有效。小型表可以直接做全表扫描,特大型表就需要分区分库等技术。

三、高性能策略

1、独立的列

        MySQL在使用索引列作为查询条件时,不正确的使用方式会使得索引失效。”独立的列“是指索引列不能是表达式的一部分,也不能是函数的参数。
        错误的列子:

where id+1=3;

where YEAR(create_time)=2023

2、前缀索引和索引选择性

        对很长的字符列建立索引,会使索引变得大且慢。对于BLOB、TEXT、VARCHAR这些列则必须使用前缀索引,因为MySQL也不允许索引这些列完整的长度。
        通常针对这些长字符列可以索引开始部分字符,这样可以减少存储空间的同时提高索引效率,但也会降低索引选择性。索引选择性越高查询效率就越高,因为选择性高的索引能过滤越多的数据行。选择性为1,性能则是最好的。

索引选择性:不重复的索引值和数据表的记录总数的比值,范围从1/数据总数到1之间。

         在索引效率和选择性之间做出合适的选择,就需要选择合适的前缀长度。下列SQL可以帮助选择合适的前缀长度。

select count(*) as num,left(列,长度) as pref

from 表

group by pref

解释:num的值越小代表选择性越高(越能过滤掉非目标数据),长度越短越效率越高(存储空间越小)

        找到合适的长度后就可以建立对应的索引列

alter  table 表名 add key(列(长度))

         前缀索引是一种能使索引更小、更快的有效方式,但是也有缺点:MySQL无法使用前缀索引进行ORDER BY和GROUP BY,也无法使用前缀索引做覆盖扫描。

3、多列索引

        在多个列上建立独立的索引大部分情况下并不会提高MySQL的查询性能。MySQL5.0及以上版本引入了一种”索引合并“策略,一定程度上可以使用表上的多个单列索引来定位指定的行。
        在MySQL5.0及以上中,查询能够同时使用多个单列索引进行扫描,并将结果进行合并。这种算法有三种:OR(unionn),AND(intersection,组合(or和and的联合及相交)。
        验证SQL是否进行了索引合并,可以使用下列例子在结果中查看。

EXPLAIN SQL语句

在结果中Extra行可以查看是否使用到了联合索引。

        索引合并策略有时候是一种优化的结果,但是上更多时候说明了表上的索引建的很糟糕

  • 当出现服务器对多个索引做相交操作时(通常有个AND条件),通常意味着需要一个包含所有相关列的多列索引,而不是多个独立的单列索引
  • 当服务器需要对多个索引做联合操作时(通常由多个OR条件),通常需要耗费大量CPU和内存资源在算法的缓存、排序和合并操作上。特别是当其中有些索引的选择性不高,需要合并扫描返回的大量数据的时候。
  • 更重要的是,优化器不会把这些计算到”查询成本“中,优化器只关心随机页面读取。这会使得查询的成本被”低估“,导致该执行计划还不如直接走全表扫描。

4、选择合适的索引列顺序

        1、创建组合索引的时候将选择性高的列放在前面。

                select * from user where type=1 and  city="LA"

        针对上述例子建立组合索引时,是建立key(type,city),还是key(city,type)。在确定顺序之前可以看看那个字段的选择性比较高。可以通过”select sum(type=1),sum(city="LA" from user)“来查看两个字段分别在表中有多少,越少的选择性越高,选择性越高索引位置越靠前。但是按照这种办法需要注意,可能对其他一些条件值的查询不公平,服务器的整体性能可能变得更糟,这需要根据实际情况做定夺

5、聚簇索引

         聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。具体的细节依赖于其实现方式,但InnoDB的聚簇索引实际上在同一结构中保存了B-Tree索引和数据行,(B+Tree)。    
        当表有聚簇索引时,数据行实际存放在索引的叶子页中。因为无法同时把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。下图为聚簇索引实例。

          对于聚簇索引InnoDB将通过主键聚集数据,如果没有主键则会选择一个唯一的非空索引代替。如果没有这种索引,InnoDB会隐式定义一个主键来作为聚簇索引。
        聚簇索引的优缺点:

优点:

  • 可以把相关数据保存在一起。例如实现邮箱,可以根据用户ID来聚集数据,读取很少的数据页就能获取某个用户的全部邮件。如果没有使用聚簇索引,则查询时可能会导致每封邮件一次I/O
  • 数据访问更快。聚簇索引将索引和数据保存在同一个B-Tree中,因此从聚簇索引获取数据通常比非聚簇索引快。
  • 使用覆盖索引扫描的查询可以直接使用页节点中的主键值。

缺点:

  • 聚簇数据最大限度提高I/O密集型应用的性能,但是数据全部放在内存中,则访问的顺序就没有那么重要,聚簇索引就没有太大的优势了。
  • 插入速度严重依赖插入顺序。按照主键的顺序插入是加载数据到InnoDB表中速度最快的方式。但如果不是按照主键顺序加载数据,那么在加载完成后最好使用OPTIMIZE TABLE命令重新组织一下表。
  • 更新聚簇索引的代价很高,会强制InnoBD将每个被更新的行移动到新的位置。
  • 基于聚簇索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能面临“页分分裂”的问题。当行的主键值要求必须将这一行插入到某个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行。页分裂会导致表占用更多的磁盘空间。
  • 聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候。
  • 二级索引(非聚簇索引)可能会更大,因为二级索引的叶子节点包含了引用行的主键。
  • 二级索引访问需要两次索引查找。(二级索引叶子节点保存的是行的主键,不是指向行物理位置的指针。通过二级索引查找行,首先找到主键,在通过主键查找聚簇索引中主键位置对应的物理位置指针,从而查找目标行。)

6、InnoDB和MyISAM的数据分布对比

        MyISAM

        他是按照数据插入顺序存储在磁盘上的。他会在表中提供一个隐藏列用于保存数据行的行号,在索引的数据结构中,每个节点都包含了索引列的值以及对应数据行的行号。(行号只针对于定长的表,非定长的表还有其他策略)
        不管是主键还是其他索引列(所有索引),列中的内容都是索引列的值+行号

        InnoDB

         InnoBD中的聚簇索引的叶子节点中包含了主键列事务ID回滚指针非事务列。非聚簇索引即二级索引的节点(可以是叶子节点、也可以是非叶子节点)的组成:索引列主键列

        InnoDB中主键的顺序问题

        对于主键(聚簇索引)建议使用自增列,而不使用UUID之类的随机数。
        采用UUID出现的问题:耗时更长、存储空间消耗的更大。
        对于顺序主键,在插入数据时会直接存储到上一条数据后面。当达到页最大填充因子时(默认15/16,剩余空间用于后期修改),下一条记录就会写入新的页中。
        对于随机主键,新的主键不一定比之前的大,所以可能需要更改以前填充满的页,就会涉及到分页、移动数据等操作。

随机主键的缺点:

  • 写入的目标页可能已经刷到磁盘上并从缓存移除,或者还没被加载到内存中。InnoDB在插入数据前找到并从磁盘读取目标页到内存中。这会导致大量I/O操作。
  • 因为写入是乱序的,InnoDB不得不频繁的做页分裂操作,以便于新的行分配空间。页分裂会导致移动大量的数据,一次插入最少需要修改三个页不是一个页。
  • 由于 频繁的页分裂,页会变得稀疏并被不规则填充,最终数据会有碎片。

顺序主键的缺点:

对于高并发工作负载,在InnoDB中按主键顺序插入可能会造成明显的争用。主键的上界会成为”热点“。因为所有的插入都发生在这里,所以并发插入可能导致间隙锁竞争。

7、覆盖索引

        概念:一个索引包含所有需要查询的字段的值。
        如果查询只需要扫描索引而无需回表带来的好处:
        (回表:二级索引查询到对应主键,在利用主键去查询主键索引中对应数据)

  • 索引条目通常远小于数据行大小,减少数据访问量、减少缓存负载、减少数据拷贝时间
  • 索引是按照顺序存储,对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O少。对于MyISAM这一类的表可以使用OPTIMIZE命令优化索引。
  • 一些存储引擎只在内存中缓存索引,数据则以来操作系统缓存,因此访问数据需要一次系统调用。这可能导致严重的性能问题,尤其是系统调用占数据访问中最大开销的场景。
  • InnoDB的二级索引在叶子节点保存了行的主键,所以二级索引能够覆盖查询,则可以避免对主键索引的二次查询。

        不是所有类型的索引都可以成为覆盖索引。覆盖索引必须存储索引列的值,而哈希索引、空间索引和全文索引等都不能存储索引列的值,所以MySQL中只能使用B-Tree索引做覆盖索引。
        当执行覆盖索引的查询时,可以看到EXPLAIN的Extra列为Using index
        索引无法覆盖查询的原因:

  • 没有任何索引能够覆盖这个查询。因为查询从表中选择了所有的列,而没有任何索引覆盖了所有的列。
  • MySQL不能在索引执行Like操作。在MySQL5.5及以前版本只允许索引做等于、不等、大于等操作。MySQL能在索引中做最左前缀匹配的Like比较,因为该操作可以转换为简单的比较操作,但如果以通配符开头的like查询,存储引擎就无法做比较匹配。

        解决上述两个问题的办法

select *

from user

inner join (select id from user where type=1 and name like "abc%") a

on a.id=user.id        

        解释:type、id、name三个字段为索引列。这种方式叫做延时关联,因为延时了对列的访问时间。在查询的第一阶段MySQL可以使用覆盖索引,在from子句中的子查询中匹配id,然后根据id去外层查询匹配获取需要的所有列的值。

8、索引扫描来做排序

        MySQL有两种方式可以生成有序结果:通过排序、按照索引顺序扫描。如果explain出来的type列的值为“index”,则说明MySQL使用索引扫描来排序。
        扫描索引本身就很快,因为只需要从一条索引记录移动到紧接着的下一条记录。但如果索引不能覆盖查询所需的全部列,那就不得不每扫描一条索引记录就要回表一次对应的行。这基本都是随机I/O,因此按照索引顺序读取数据的速度通常比顺序地全表扫描慢,尤其是在I/O密集型的工作负载时。
        只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向都一样时,MySQL才能使用索引对结果排序。如果查询需要关联多张表,则只有当ORDER BY子句引用的字段全部为第一张表时,才能使用索引排序。ORDER BY和查询的限制是一样的:需要满足索引的最左前缀的要求
        有种情况可以不用满足最左前缀原则:where和order by后面的条件字段加起来满足最左前缀原则。这样即使order by子句不满足最左前缀的要求,也可以用于查询排序。例子:

select type,name from user where type=2 order by name

解释:user表中有组合索引,其顺序为:type,name。则这种情况下也会走索引排序。

        下列例子是一些不能做索引排序的查询(假设下列例子中的有组合索引(type,name,num)):

  • 查询使用了两种不同的排序方向
    select  *  from user where  type=2  order by  name desc , num asc;
  • order by 中引用了不在索引中的列
    select  *  from user where  type=2  order by  name desc , create_time asc;
  • where和order by中的条件无法组成最左前缀原则
    select  *  from user where  type=2  order by num;
  • 查询索引列存在范围查询
    select  *  from user where  type>2  order by num;
    select  *  from user where  type=2 and name in(1,2) order by num;

 

四、索引案例

        1、建立组合索引可以把查询率高的字段放前面,不管他的选择性高低。

        查询率较高,就算需要过滤这个字段,也可以使用通过 “in (男,女)”这种方式,容易满足最左前缀原则。但是in的值太多,这种方式就不适用。

        2、容易进行范围查询的字段放到后面去。

        为了尽可能使用更多的列进行索引,而查询只能使用最左前缀,直到遇到第一个范围查询条件列。比如日期这一字段,一般查询就是在一个日期到另一个日期之间。

        3、避免多个范围条件

        范围条件可以使用explain查看,type列为range类型则是范围查询。
        where age>2

        where age in (1,2,3)

        上述两个例子都是范围查询。但是第一个例子会是索引失效,而第二个不会,因为第二个是“多个等值条件查询”

        MySQL的索引无法进行两个及以上的范围查询,所以在范围查询时可以使用in代替(in的值不建议太多)。

五、维护索引和表

        维护表的目的:找到并修复损坏的表,维护准确的索引信息,减少碎片。

1、找到并修复损坏的表

        MyISAM存储引擎
        表损坏通常是系统崩溃导致的。也可能是硬件、MySQL设计缺陷、操作系统内的问题导致索引损坏。
        损坏的索引会导致查询返回错误的结果或者莫须有的主键冲突等问题,严重时还会导致数据库的崩溃。可以使用check table(有些存储引擎不支持)来检查是否发生了表损坏。
        找出错误后可以使用repair table 命令来修复损坏的表,但不是所有存储引擎支持该命令。

        InnoDB
       
对于InnoDB不支持上述命令修复,可以使用alter talbe命令来重建表

alter table user  engine=innodb

        但是对于InnoDB来说,出现了损坏,那一定发生了严重的错误,需要找到损坏的原因。如果出现损坏,可能是内存或者磁盘的问题,也可能是在MySQL外部操作了数据文件。

2、减少索引和数据碎片

        B-Tree索引可能会碎片化,这回降低查询的效率。碎片化的索引可能会以很差或无序的方式存储在磁盘上。
        一下是三种数据碎片:

  • 行碎片
    这种碎片指的是数据行被存储为多个地方的多个片段中。即使查询只从索引中访问一行记录,行碎片也会导致性能下降。
  • 行间碎片
    逻辑上顺序的页,或者行在磁盘上不是顺序存储的。行间碎片对诸如全表扫描和聚簇索引扫描之类的操作有很大的影响,因为这些操作原本能够从磁盘上顺序存储的数据中获益。
  • 剩余空间碎片
    数据页中有大量的空余空间。这会导致服务器读取大量不需要的数据。

        对于MyISAM表这三类碎片化都可能发生。但InnoDB不会出现短小的行碎片,InnoDB会移动短小的行并重写到一个片段中。
        可以通过执行optimize table或者导出再导入的方式来重新整理数据。对于不支持optimize table的存储引擎,可以通过一个不做任何操作的alter table来重建表。

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

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

相关文章

Java10新增特性

版本介绍 Java 10 的发布时间是2018年3月20日。这是在Java 9之后&#xff0c;采用了基于时间发布的策略&#xff0c;每6个月一个版本。这是采用新的发布策略之后的第一个版本。 Java 10 是Java版本历史上最快的一个版本。它打破了Java缓慢增长和进化的概念。它是一个具有许多…

【树与二叉树的转换,哈夫曼树的基本概念】

文章目录 树与二叉树的转换将二叉树转化为树森林与二叉树的转化&#xff08;二叉树与多棵树之间的关系&#xff09;二叉树转换为森林森林的先序遍历1&#xff09;先序遍历2&#xff09;后序遍历 哈夫曼树的基本概念森林转换成二叉树&#xff08;二叉树与多棵树的关系&#xff0…

Sensor 点亮出图后,颜色偏红或者偏绿是为什么?

这是因为 sensor balck level 的值配置的不正确导致&#xff0c;black level 的值一般在效果参数的 calibration 参数里面。 在驱动调试阶段&#xff0c;我们一般都是复用其他已调试好的&#xff0c;sensor 的驱动文件及效果文件&#xff0c; 而不同 sensor 的 balck level 的…

YOLOv8-Seg改进:分割注意力系列篇 | 高效的通道先验卷积注意力(CPCA) | 中科院 2023.6

🚀🚀🚀本文改进:高效的通道先验卷积注意力(CPCA)方法,支持注意力权重在通道和空间维度上的动态分布; 🚀🚀🚀CPCA 小目标分割检测&复杂场景首选,实现涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新…

奇舞周刊第510期:浏览器和图形引擎渲染对比

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 浏览器和图形引擎渲染对比 本文从介绍浏览器渲染引擎开始&#xff0c;逐渐引出和图形引擎的比较&#xff0c;尝试从图形视角探索和理解浏览器的渲染原理。 Next.js的崛起&#xff…

消息队列使用场景

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇记录消息队列使用场景&#xff0c;如有出入还望…

基于STC12C5A60S2系列1T 8051单片机串口通信信应用

基于STC12C5A60S2系列1T 8051单片机串口通信应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机串口通信介绍STC12C5A60S2系列1T 8051单片机串口通信的结构基于STC12C5A60S2系列1T 8051单片机串口通信的特殊功能寄存器列表基于STC12C5A60S2系列1T 8051单片…

力扣字符串--总结篇

前言 字符串学了三天&#xff0c;七道题。初窥kmp&#xff0c;已经感受到算法的博大精深了。 内容 对字符串的操作可以归结为以下几类&#xff1a; 字符串的比较、连接操作&#xff08;不同编程语言实现方式有所不同&#xff09;&#xff1b; 涉及子串的操作&#xff0c;比…

Sagemaker基础操作指南

简介 Amazon SageMaker是亚马逊AWS提供的一项托管式机器学习服务&#xff0c;旨在简化和加速机器学习开发的整个生命周期。它为机器学习工程师和数据科学家提供了一套完整的工具和功能&#xff0c;用于构建、训练、调优和部署机器学习模型。本文将会通过一个简单的例子&#x…

linux_day02

1、链接&#xff1a;LN 一个点表示当前工作目录&#xff0c;两个点表示上一层工作目录&#xff1b; 目录的本质&#xff1a;文件&#xff08;该文件储存目录项&#xff0c;以链表的形式链接&#xff0c;每个结点都是目录项&#xff0c;创建文件相当于把目录项添加到链表中&…

111111111111111

全局锁 就是对整个数据库进行加锁&#xff0c;加锁之后整个数据库就处于只读状态&#xff0c;后续的DML写语句&#xff0c;DDL语句&#xff0c;以及对更新事务的提交操作都会被阻塞&#xff0c;典型地使用场景就是做整个数据库的逻辑备份&#xff0c;对所有的表进行锁定&#x…

LIBGDX实时绘制字符、实时绘制中文

LIBGDX实时绘制字符、实时绘制中文 转自&#xff1a;https://lingkang.top/archives/libgdx-shi-shi-hui-zhi-zi-fu 注意&#xff0c;相比于贴图字体&#xff0c;实时绘制会有一定的失真、模糊 Maven项目依赖&#xff1a; <properties><maven.compiler.source>…

【Java 进阶篇】Java中的 JSP(JavaServer Pages)

JavaServer Pages&#xff08;JSP&#xff09;是一种用于开发动态Web页面的Java技术。它是在静态Web页面中嵌入Java代码的一种方式&#xff0c;使得开发者可以借助Java的强大功能来创建动态、交互性强的Web应用程序。在本文中&#xff0c;我们将深入探讨JSP的概念、原理和基本用…

算法:FloodFill算法

文章目录 算法原理图像渲染岛屿数量岛屿的最大面积被围绕的区域太平洋大西洋水流问题扫雷游戏衣橱整理 算法原理 FLoodFill算法通俗来讲&#xff0c;就是洪水给地势带来的变化&#xff0c;而实际上题目要求的就是一个连通块问题&#xff0c;那本质还是暴搜和DFS/BFS相结合&…

vue做的一个一点就转的转盘(音乐磁盘),点击停止时会在几秒内缓慢停止,再次点击按钮可以再次旋转,

先看效果&#xff1a; 代码&#xff1a;主要部分我会红线画出来 css:部分&#xff1a; 源码&#xff1a; vue部分&#xff1a; <template><div class"song-lyric"><div><div class"type"><div class"right">&l…

【Git】git常用命令大全

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Git》。&#x1f3af;&#x1f3af; &#x1f449…

实体店铺必看:如何申请低手续费或免手续费的收款码

在数字支付日益普及的今天&#xff0c;为实体店铺如餐饮店引入低成本甚至免手续费的收款解决方案变得尤为重要。本文将详细介绍实体店铺如何申请低手续费或免手续费的收款码&#xff0c;助您降低运营成本&#xff0c;提升业务效率。 一、了解不同支付平台的政策 首先&#xf…

性能测试之性能调优详解

性能测试是通过模拟实际使用场景&#xff0c;对系统进行压力测试和负载测试&#xff0c;以评估系统的性能指标&#xff0c;如响应时间、吞吐量和并发能力等。通过性能测试可以发现系统的瓶颈和性能问题&#xff0c;并针对性地进行优化。 监控工具可以实时监测系统的运行状态和…

gorm使用之各种表关系实例-主外键->struct

gorm使用之各种表关系实例-主外键->struct 一对多关系(用户与文章) 如: 老板与员工 女神和舔狗 老师和学生 班级与学生 用户与文章 ...以用户与文章举例 models应当如,注意&#xff01;&#xff01;&#xff1a;User表中的ID应当与Article中的UID一直&#xff0c;大小和…

搞怪python代码

微信消息重发代码&#xff1a; from pynput.keyboard import Key,Controller import time keyboard Controller()a input("请输入你需要循环输出的内容&#xff1a;") b eval(input(请输入你想要循环的次数&#xff1a;)) print("数据已接收&#xff01;请将…