Mysql的重要知识点以及问题

查看索引的命令

     show   index  from  mytable

索引的原理

索引用来快速地寻找那些具有特定值的记录。如果没有索引,⼀般来说执行查询时遍历整张表。

索引的原理:就是把无序的数据变成有序的查询

  1. 把创建了索引的列的内容进行排序

  2. 对排序结果生成倒排表

  3. 在倒排表内容上拼上数据地址链

  4. 在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据

索引的优缺点

优点:   1.有助于加快数据的检索 , 降低数据库IO的成本,  这也是创建数据库索引的原因,  在查询数据库数据时, 不用进行全表扫描

           2.通过创建唯一性索引,  也可以保证数据库中每一行数据的唯一性

           3.优化排序, 聚合, 分组的操作,  主要是因为索引可以提供预排序和预分组的功能,从而避免了数据库在排序和分组时需要进行大量的计算和比较操作。具体来说,索引可以按照某个或某些列的值来对数据进行排序或分组,这样在查询时,数据库就可以直接利用索引的排序或分组顺序来返回数据,而不需要进行额外的比较或计算操作 ,  降低的CPU的消耗.

           4.改善并发性能,  索引可以提高数据库的并发性能,  他可以减少锁定表, 行, 页 等资源的时间

           5.可以加速表与表之间的连接

缺点:  1.创建索引和维护索引需要耗费时间,  当数据量大的时候更为明显,

           2.索引需要占用存储空间, 因为它需要存储索引列的值和指向数据行的指针

           3.表中的数据进行增加,  删除,  更改时,  索引也要动态的进行维护,  提高了CPU的消耗

给字段加索引

建议创建索引的情况

1.频繁用作查询条件的列 , 如果某个列经常被用作查询条件,那么在该列上创建索引可以提高查询的效率。例如在一个用户表中,如果经常根据用户的ID查询用户信息,那么在ID列上创建索引可以提高查询效率。

2.连接表的列 , 如果数据库中需要经常进行表连接操作,那么可以在连接列上创建索引,以加快连接的速度。例如在一个订单表中,如果经常需要连接用户表查询用户信息,那么在用户ID列上创建索引可以提高连接的效率。

3.经常用作排序的列 , 如果某个列经常用作排序条件,那么在该列上创建索引可以提高排序的效率。例如在一个商品表中,如果经常需要按照价格进行排序,那么在价格列上创建索引可以提高排序的效率。

4.大表中访问次数少的列,  在数据库中,索引是一种用于加快查询速度的数据结构。当在大表中进行查询时,如果没有索引,数据库将需要按顺序扫描整个表来找到匹配的行。如果表很大,这可能会非常慢。加索引可以大大提高查询速度,因为它可以将搜索时间从线性搜索降至对数搜索,而对数搜索的时间复杂度更低。因此,对于大表中访问次数较少的列,为其加索引可以帮助数据库更快地找到匹配的行。然而,需要注意的是,索引也会增加写入操作的时间,因为每次插入、更新和删除操作都需要更新索引。因此,在决定是否为某个列添加索引时,需要权衡查询速度和写入速度之间的权衡,并根据具体情况做出决策。

不建议创建索引的情况

1.对数据表查询时很少引用到的、大量重复的字段不应该创建索引。

2.数据量非常小的数据表,索引能够改进其数据访问的效率十分有限,不必创建索引。

3.对于一个基本表不应该建立过多的索引,数据表进行增删改时,索引也随之变化。索引需要占用文件目录和存储空间,而且需要维护,过多会使系统负担加重。

什么情况下使用符合索引更好?

1.组合索引

       组合索引是指将多个列作为一个索引来创建的索引。与单列索引不同,组合索引可以同时包含多个列,并且可以按照这些列的顺序来进行搜索和排序。在使用组合索引时,数据库会首先按照第一个列进行排序,然后按照第二个列排序,以此类推。这种排序方式可以提高查询速度,尤其是在需要同时过滤多个列的条件时,组合索引可以非常有效。需要注意的是,组合索引并不是越多越好。通常情况下,只需要在经常用于查询的列上创建索引即可。在选择组合索引的列时,需要考虑到查询的频率、过滤条件的数量和列的顺序等因素。不合理的组合索引可能会降低性能,甚至会导致查询变慢。因此,在创建组合索引时,需要根据实际情况进行权衡和选择。

组合索引也可以成为复合索引,一个索引包含多个列,组合索引比单值索引开销更小(对于相同的多个列建索引),  这是因为组合索引可以减少索引的数量,从而降低索引的维护和存储开销。

2.组合索引最左前缀原则

     在使用组合索引的列作为太监时, 必须要出现在最左侧列为条件, 否则索引不生效,  这是因为组合索引是按照列顺序进行排序的,查询时只要按照索引列的顺序依次匹配查询条件即可。如果查询条件不满足最左前缀列的条件,那么索引就无法使用,查询将转换为全表扫描。因此,在设计组合索引时,需要根据实际情况选择索引列的顺序,以确保最常用的查询可以使用索引。同时,需要避免过度索引,即创建过多的组合索引,因为这可能会降低写入性能,增加索引维护的开销。

什么情况索引会失效

1.组合索引最左前缀原则:在使用组合索引的列作为条件时,必须要出现最左侧列为条件,否则索引不生效

2.条件中有or, 即使其中有条件带有索引也不会生效

      这是因为 OR 运算符会将查询条件分为多个子条件,每个子条件可能需要使用不同的索引。如果每个子条件都能使用索引,那么索引可能会被使用。但是,如果其中一个子条件没有索引或者多个子条件的索引不能被合并使用,那么索引就会失效。

避免索引失效 :  可以考虑将多个单列索引合并为组合索引,以便在查询条件中包含多个列时能够使用索引。此外,还可以将 OR 运算符转换为 UNION 运算符,将查询拆分为多个子查询,每个子查询只包含一个条件,从而避免索引失效的问题。

3.like查询以%张三 , %臧三%

避免索引失效 :  可以考虑将 LIKE 运算符的模式匹配改为以通配符结尾,或者将 LIKE 运算符改为等于(=)运算符,从而能够使用索引进行优化。另外,还可以使用全文搜索引擎等其他技术来优化模糊查询。

全文搜索引擎 : 全文搜索引擎的原理是将文本内容中的每个单词都分词,并将分词结果建立索引。当用户输入查询语句时,搜索引擎会对查询语句进行分词,并在索引中查找匹配的单词。全文搜索引擎使用的索引通常是倒排索引,也就是将每个单词出现的位置与该单词建立映射关系,从而能够快速定位文本内容中包含该单词的位置。

4.字符串类型的字段,传入了int类型的参数时索引会失效,而int类型的字段传入字符串类型不会失效。Mysql是根据自己数据类型转换规则来进行转换的

为什么使用模糊匹配会失效

        这是因为 LIKE 运算符的模式匹配以通配符开头时,无法使用索引进行优化。因为在索引中,数据是按照索引列的顺序进行排序的,而 LIKE 运算符的通配符开头表示不能利用索引的排序特性。

索引其实就是排序 , 或者说排队

like '张三%',实际你要找的是'张三XXX',只要把所有'张三'开头的那部分内容返回即可,这部分是连续的,不需要全表扫描。 like '%张三',实际你要找的是'XXX张三',这部分在索引里是不连续的,如果要返回需要的结果,只能全表扫描。

联合索引的好处是什么?

1.减少索引建立的开销

           建了一个(a,b,c)的复合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,因为每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,这可是不小的开销!

2.索引覆盖

           索引覆盖是指查询可以仅通过索引就可以完成,而无需访问表中的实际数据行。当查询的列都包含在索引中时,查询就可以使用索引覆盖来避免访问表中的实际数据行,从而提高查询性能。

使用索引覆盖的好处是可以避免查询大量的数据行,从而节省了 I/O 操作和 CPU 时间。此外,由于索引通常比数据行更小,因此查询也可以更快地从磁盘读取索引数据。

需要注意的是,在选择是否使用索引覆盖时,需要根据实际情况进行权衡。如果查询需要访问表中的大部分数据行或需要返回表中的多列数据,那么使用索引覆盖可能不是最优的选择,因为这会增加索引的扫描次数和 I/O 操作次数。

3.减少扫描行数

(1)当使用联合索引进行查询时,如果联合索引中包含了聚簇索引列,那么查询就可以直接从聚簇索引中获取所需数据,无需再扫描数据行,从而减少了 I/O 操作和 CPU 时间。

例如,假设有一个包含两列的表,分别为 A 和 B,并且为 A 列和 B 列分别创建了单列索引,并且 A 列是聚簇索引列。如果查询语句中只需要返回 A 列的值,那么查询可以使用如下语句:

SELECT A FROM table WHERE B = 'value'

在这个查询中,虽然查询语句中只包含了 B 列,但是 A 列是聚簇索引列,因此查询可以直接从聚簇索引中获取所需数据,无需再扫描数据行,从而减少了扫描行数。

(2)非聚簇索引是指将索引键值和指向数据行的指针分开存储的索引方式。由于索引和数据行存储在不同的页中,因此非聚簇索引的查询效率相对较低。当使用联合索引进行查询时,如果联合索引中包含了非聚簇索引列,那么查询就需要通过索引键值查找到指向数据行的指针,再去访问实际数据行,从而增加了 I/O 操作和 CPU 时间。

例如,假设有一个包含两列的表,分别为 A 和 B,并且为 A 列和 B 列分别创建了单列索引,并且 B 列是非聚簇索引列。如果查询语句中只需要返回 A 列的值,那么查询可以使用如下语句:

SELECT A FROM table WHERE B = 'value'

在这个查询中,虽然查询语句中只包含了 B 列,但是 B 列是非聚簇索引列,因此查询需要通过索引键值查找到指向数据行的指针,再去访问实际数据行,从而增加了扫描行数。

需要注意的是,联合索引的效率取决于查询的具体情况和索引的类型。如果联合索引中包含了聚簇索引列,那么查询就可以直接从聚簇索引中获取所需数据,从而减少扫描行数;如果联合索引中只包含了非聚簇索引列,那么查询就需要通过索引键值查找到指向数据行的指针,再去访问实际数据行,从而增加扫描行数。因此,在创建联合索引时需要根据实际情况进行权衡,选择合适的列进行组合索引,以充分发挥索引的优势。

联合索引使用的场景

         假设这个系统中有一个订单表,包含以下列:订单号、用户ID、订单状态、订单时间、货物名称、货物数量、货物价格等。如果我们需要根据用户ID和订单状态查询某个用户的所有已完成订单,那么可以为用户ID和订单状态创建一个联合索引。

当我们发起这个查询时,系统会在联合索引中查找符合用户ID和订单状态条件的所有订单。由于联合索引是由多个列组成的索引,可以在多个列上进行搜索,因此系统可以使用联合索引来完成查询,从而减少扫描行数,提高查询效率。如果没有联合索引,系统可能需要扫描整个订单表,根据用户ID和订单状态来筛选符合条件的订单,这样会增加查询的时间和资源消耗。

因此,在订单管理系统中使用联合索引可以提高查询效率,加快订单的处理速度,提高用户体验。

Mysql慢查询该如何优化

1.检查是否走了索引 , 如果没有则优化sql利用索引

2.检查所利用的索引是否是最优索引

3.检查锁查的字段是否都是必须的 , 是否查询了过多的字段 , 查出了多余的数据

4.如果检查表的数据过多 , 是否应该进行分库分表

5.检查数据库实例所在的机器的性能配置是否太低 , 是否可以适当的增加资源

Explain与Sql优化

比较重要的几个字段:

possible_keys: 代表可能用到的索引

key:实际上使用的索引

key_len:实际使用索引的长度

type所显示的是查询使用了哪种类型,type包含的类型包括如下图所示的几种:

从最好到最差依次是:

system > const > eq_ref > ref > range > index > all

1.system:表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计
2.const:单表中最多只有一个匹配行(主键或唯一索引),在优化阶段即可读到数据
3.eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
4.ref:普通索引
5.range:范围查询,一般就是在你的where语句中出现between、< 、>、in等的查询,
6.index: 遍历索引树。这通常比ALL快,但是也没好到哪里去。
7.all:全表扫描,最差的情况下

Using index:表示相应的select操作中使用了覆盖索引(Covering Index)

Using where:表明使用了where过滤

Mysql怎么判断走索引还是全表扫描

        我们在查询有索引的字段时,有时候会发现居然没有走索引,而是走了全表扫描,因为MySQL发现走全表扫描会比走索引更快,因此选择了全表扫描。

例如:我们给字段bcd加了联合索引,然后查询sql为select * from t1 where b>1

例如 :  你走了联合索引,就会找到七条符合条件的记录,然后要进行七次回表查询(因为是select *,还有其他字段不在当前索引树中),所以mysql认为与其你先走了索引然后进行许多次的回表查询,不如直接全表扫描快,于是就虽然你用了索引但是还是全表扫描了。

小结:mysql会进行成本计算,用了索引的成本是多少,全表扫描的成本是多少,如果用了索引但是回表太多就去全表扫描

关系型和非关系型数据库的区别 , 以及使用场景

1.关系型数据库 :采用关系模型来组织数据的数据库,关系模型就是二维表格模型。一张二维表的表名就是关系,二维表中的一行就是一条记录,二维表中的一列就是一个字段。

优点:容易理解 ,使用方便,通用的 sql 语言 ,易于维护,丰富的完整性(实体完整性、参照完整性和用户定义的完整性)。

缺点:磁盘 I/O 是并发的瓶颈 ,海量数据查询效率低 ,横向扩展困难,无法简单的通过添加硬件和服务节点来扩展性能和负载能力, 需要对数据库进行升级和扩展时,需要停机维护和数据迁移 ,多表的关联查询以及复杂的数据分析类型的复杂 sql 查询,性能欠佳。因为要 保证 ACID.

2.非关系型数据库:分布式,一般不保证遵循 ACID 原则的数据存储系统。键值对存储, 结构不固定。

优点:结构简单易扩展 ,高性能灵活的数据模型

缺点:只适合存储一些较为简单的数据 ,不适合复杂查询的数据 ,不适合持久存储海量数据,  因此适合存储较为简单的数据。有一些不能够持久化数据,所以需要和关系型数据库结合。

例如自己存数据都是用的关系型MySql数据库,但是用到了非关系型数据库redis去做一个缓存以及分布式锁,自己的邮箱验证码和新闻就是存在redis中去的。

左匹配 , 右匹配 , inner join说一下区别

区别:

1.left以left join 左侧的表为主表 , 左表中的记录都会出现在查询结果中 , 如果右表没有相匹配的结果,  则以null来填充

2.right 以 right join 右侧表为主表,记录都会出现在查询结果中,如果左表没有相匹配的记录,则以 null填充。

3.inner join 查找的数据是左右两张表共有的

什么是小表驱动大表?

用小的数据集驱动大的数据集

1.当使用left join时,左表是驱动表,右表是被驱动表 ;

2.当使用right join时,右表时驱动表,左表是被驱动表 ;

3.当使用inner join时,mysql会选择数据量比较小的表作为驱动表,大表作为被驱动表 ;

例如:现有两个表A与B ,表A有200条数据,表B有20万条数据 ; 按照循环的概念举个例子

小表驱动大表 for(200条){ for(20万条){ ... }

大表驱动小表 for(20万){ for(200条){ ... }

总结:

1.如果小的循环在外层,对于表连接来说就只连接200次 ; 2.如果大的循环在外层,则需要进行20万次表连接,从而浪费资源,增加消耗 ;

综上: 小表驱动大表的主要目的是通过减少表连接创建的次数,加快查询速度 。

外键

外键约束可以实现以下功能:

  1. 强制引用完整性:外键约束可以强制要求关联表之间的数据必须保持一致,从而避免了不一致的数据出现。

  2. 防止孤立行:外键约束可以防止在关联表中删除数据时出现孤立行的情况,从而保证了数据的完整性。

  3. 自动更新关联数据:外键约束可以自动更新关联表中的数据,从而保证了数据的一致性。

1.外键可以保证数据的完整性和一致性 , 不会得到孤立行

2.可以获得良好的"级联删除 , 级联更新" ,  自动的清理表

3.将数据完整性判断托付给了数据库完成,减少了程序的代码量

4.外键提供了一个非常重要的提示,说明在数据库中收集哪些统计信息最重要。

不使用外键的原因

1. 数据库需要维护外键的内部管理

2. 外键等于把数据的一致性事务实现,全部交给数据库服务器完成,使数据库在每个CRUD操作上都额外工作,因为它必须检查外键一致性,这要消耗不少资源,如果进行大批量更新,这更是非常痛苦。

3.通过强制关系,外键指定了您必须添加/删除内容的顺序,例如如果学生关联了订单,必须先删除订单数据,在删除学生数据。

4.外键还会因为需要请求对其他表内部加锁而容易出现死锁情况。

具体来说,假设有两个表 A 和 B,它们之间存在外键约束,A 表的某个记录被 B 表的某个记录引用。在进行并发操作时,如果两个事务分别要修改 A 表和 B 表的相关记录,就会出现如下的死锁情况:

  • 事务 1 先获取了 A 表的锁,然后想要获取 B 表的锁;
  • 事务 2 先获取了 B 表的锁,然后想要获取 A 表的锁;
  • 由于两个事务的获取顺序相反,因此它们会陷入死锁状态,无法继续执行。

为了避免这种情况,可以采用以下方法:

  1. 优化事务的顺序和方式,避免对多个表进行并发操作。

  2. 采用更加细粒度的锁粒度,以减少锁的竞争和冲突。

  3. 使用数据库的死锁检测和自动回滚机制,以确保事务的执行顺序和一致性。

InnoDB和MyISAM的区别

InnoDB 和 MyISAM 是 MySQL 数据库中最常用的两种存储引擎,它们在数据存储、索引、事务处理等方面有着不同的特点和适用场景。

1.存储方式

MyISAM 存储引擎采用表级锁定,对于读操作和写操作是互斥的,不能同时进行。而 InnoDB 存储引擎采用行级锁定,对于读操作和写操作是并发的,可以同时进行。

2.支持的事务

MyISAM 存储引擎不支持事务,而 InnoDB 存储引擎支持事务,并且具有 ACID 属性,可以保证数据的一致性、隔离性、持久性和原子性。

3.索引

MyISAM 存储引擎对于大量的查询操作有很好的性能表现,尤其是在全文索引方面。而 InnoDB 存储引擎对于大量的写操作和事务处理有很好的性能表现,尤其是在高并发的情况下。

4.外键约束

MyISAM 存储引擎不支持外键约束,而 InnoDB 存储引擎支持外键约束,并且可以保证关联表之间的数据完整性和一致性。

5.数据安全性

MyISAM 存储引擎在出现故障时,容易发生数据损坏和数据丢失的情况。而 InnoDB 存储引擎采用事务日志和回滚日志等机制,可以保证数据的安全性和完整性。

综上所述,MyISAM 存储引擎适用于读操作较多、对事务处理和数据安全性要求不高的场景,而 InnoDB 存储引擎适用于需要事务处理和数据安全性保障的场景,尤其是对于并发写操作和外键约束有较高要求的场景。

数据库的隔离级别

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

注意:在innodb存储引擎下,引入mvvc之后已近解决了幻读问题。

Mysql的锁有哪些

MySQL 数据库中的锁包括以下几种类型:

1.表级锁

表级锁是一种最基本的锁,它可以锁定整个表,对于读操作和写操作是互斥的,不能同时进行。表级锁适用于对于数据进行批量操作时,可以有效地控制并发的访问。

2.行级锁

行级锁是一种更加细粒度的锁,它可以锁定表中的某一行数据,对于读操作和写操作是并发的,可以同时进行。行级锁适用于对于数据进行单行修改、删除、插入等操作时,可以提高并发性。

3.共享锁和排他锁

共享锁是一种读锁,在共享锁下,多个事务可以同时读取同一行数据,但是不能进行写操作。排他锁是一种写锁,在排他锁下,只能有一个事务进行写操作,其他事务不能进行读写操作。

4.间隙锁

间隙锁是一种特殊的锁,它可以锁定索引中的空隙,防止其他事务在空隙中插入数据。间隙锁适用于多个事务同时插入数据的场景,可以避免出现重复数据的情况。

5.意向锁

意向锁是一种辅助锁,它可以通知其他事务将要对数据进行怎样的操作(读或写),从而避免锁的冲突。意向锁适用于锁定表时,可以提高锁的效率和性能。

需要注意的是,不同的锁在应用场景和使用方法上有所不同,应该根据实际情况选择合适的锁类型,并合理设计数据库表结构和索引,以提高数据库的并发性和可扩展性。

MVCC 的目的就是多版本并发控制,在数据库中的实现,就是为了解决读写冲突,它的实现原理主要是依赖记录中的 3个隐式字段undo日志Read View 来实现的。所以我们先来看看这个三个 point 的概念。

MVCC实现原理

Read View:说白了 Read View 就是事务进行快照读操作的时候生产的读视图 (Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的 ID (当每个事务开启时,都会被分配一个 ID , 这个 ID 是递增的,所以最新的事务,ID 值越大)。

undo log :实际上就是存在 rollback segment 中旧记录链。

隐式字段:每行记录除了我们自定义的字段外,还有数据库隐式定义的 最近修改(修改/插入)事务 ID, 回滚指针,指向这条记录的上一个版本, 隐含的自增 ID(隐藏主键) 等字段。

正是 Read View 生成时机的不同,从而造成读已提交 , 可重复读级别下快照读的结果的不同;总之在 读已提交隔离级别下,是每个快照读都会生成并获取最新的 Read View;而在可重复读隔离级别下,则是同一个事务中的第一个快照读才会创建 Read View, 之后的快照读获取的都是同一个 Read View。

说一说select... 这个查询语句 , 在mysql查询的过程

mysql分为server层与存储引擎层,server层包含连接器、分析器、优化器、执行器。

接下来以一条sql查询语句执行过程介绍各个部分功能。客户端执行一条sql:

1、连接器:连接到数据库,身份验证,权限管理

2、分析器:执行之前,MySQL肯定需要知道你要做啥,先进行词法分析,把关键字识别出来,再进行语法分析,看你的SQL语句语法是否有错。

3、优化器:通过分析器,我们知道了SQL需要做什么,但是直接根据SQL去获得结果可能会消耗很大性能,因此还得需要经过优化器对其进行优化。生成执行计划、选择索引等操作,选取最优执行方案

4、执行器,打开表调用存储引擎接口,逐行判断是否满足查询条件,满足放到结果集,最终返回给客户端;若用到索引,筛选行也会根据索引筛选。

说说redolog 和 undolog 日志的过程

redo log作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。

内容:

物理格式的日志,记录的是物理数据页面的修改的信息,其redo log是顺序写入redo log file的物理文件中去的。什么时候产生:事务开始之后就产生redo log,redo log的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo log文件中。

undo log作用:如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。

内容:可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

猜你喜欢

转载自blog.csdn.net/weixin_71243923/article/details/130605476
今日推荐