当前位置: 首页 > news >正文

MySQL笔记8

一、索引

1.索引介绍

日常生活类比:如电话号码簿按“姓”查号码、字典按“字母”查单词,“姓”和“字母”可看作索引,按其查询就是按索引查询。

数据库定义:索引(index)是帮助MySQL高效获取数据的有序数据结构。数据库系统在数据之外维护满足特定查找算法的数据结构,这些结构引用数据,可实现高级查询算法。MySQL中所有数据类型都可被索引。

本质与作用:是一种特殊文件,用于快速查询数据库表中特定记录,是提高数据库性能的重要方式。

索引的特性:

  是数据库模式(schema)中的数据对象。

  有序数据结构,加速表的查询。

  与表独立存放,但必须属于某个表,不能独立存在。

  由数据库自动维护,表被删除时,表上的索引自动删除。

  作用类似书的目录,几乎每张表都有索引。

2.表有无索引的查询方式

(1)无索引的查询方式

  无索引时,执行SQL语句会全表扫描,即按照表格顺序遍历每一条数据获取查询数据,性能极低。

如下:建表时没有给任何列添加索引,插入测试数据并执行查询 age>30 的记录时。MySQL会执行全表扫描:数据库会从表的第1行开始,逐行检查 age 的值是否小于30。依次遍历 id=1 到 id=10 的所有记录,最终筛选出 age 符合条件的行。

这种方式需要遍历表中所有记录,当表中数据量很大时,查询性能会非常低

(2)有索引的查询方式

B+tree索引数据结构

组成:根节点→子节点→叶子结点

  以3阶B+Tree为例,根节点下可有3个子节点,每个节点最多存储2个key、3个指针。

  非叶子节点起索引作用,叶子节点存放数据,且叶子节点形成单向链表,每个节点通过指针指向下一个节点。MySQL对经典B+Tree优化,增加相邻叶子节点的链表指针,形成带顺序指针的B+Tree,提高区间访问性能,利于数据排序操作。

节点裂变:当节点中key值不满足阶数要求时开始裂变,中间元素向上分裂,所有key值转化到叶子节点。查询时,值小于key在左节点,大于等于key在右节点。

查询效率:通过B+Tree的索引结构,无需全表扫描,可快速定位到满足条件的数据,大幅提升查询性能。例如查询 age<30 的记录时,可通过B+Tree直接定位到对应叶子节点的数据,避免遍历所有记录。

Hash索引

原理:将无序数据转化为有序查询,步骤如下:

  对索引列的每行数据计算Hash值。

  对索引列的所有值再次通过Hash函数计算对应的槽位。

  在槽位中记录key值和该行的Hash值,以此建立索引。

  Hash冲突:当多个key值计算到同一个槽位时,通过Hash链表解决,在对应值后添加链表。

例:

  第一步:先通过hash算出该表中每一行数据的hash值

  第二步:拿到name字段的所有值,根据所获取的所有值再次通过内部的hash函数来计算每一个name值应该对应在hash表的哪一个槽位中;

  第三步:如金庸这个键值计算出所对应的槽位是005,则在该槽位中记录key值和该行的hash值。以此类推

Hash冲突:

  当两个或者多个key值计算的是同一个槽位则出现了hash冲突(hash碰撞),解决方式通过hash链表来解决,在对应的值后添加链表

特点:

  仅支持等值比较( = 、 in ),不支持范围查询。

  无法利用索引实现排序。

  查询效率高,无冲突时通常只需一次查询。

R-tree空间索引

支持版本:MySQL 5.7及之后版本,且支持OpenGIS几何数据模型,使用较少,了解即可。

类型含义说明
Geometry空间数据

任何一种空间类型

INSERT INTO 表名 (字段名) VALUES(POINT(121.4737, 31.2304))

Point

坐标值

INSERT INTO 表名 (字段名) VALUES (POINT(1, 2))

LineString线

有一系列点连接而成,至少两个坐标点

INSERT INTO 表名 (字段名) VALUES (LINESTRING(1 2, 3 4, 5 6))

Polygon多边形

由多条线组成

INSERT INTO 表名 (字段名) VALUES (POLYGON((0 0, 0 10, 10 10, 10 0, 0 0)))

操作:

两个语句在功能上是等价的,只是语法表述略有不同,都是为表中的 geom_point 字段创建一个空间索引。

3.索引优缺点

优势劣势
提高查询效率-提高数据检索的效率,降低数据库的IO成本索引列也是要占用空间的
提高排序效率-通过索引列对数据进行排序,降低数据排序成本,降低CPU的消耗索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行insert update、delete时,效率降低

4.索引分类

按 数据结构 分: B+tree索引、hash索引、full-text索引、r-tree 空间索引

按 物理存储 分:聚簇索引、二级索引(辅助索引)非聚簇索引

按 字段特性 分:主键索引、唯一索引、普通索引、前缀索引,fulltext index,spatial index

按 字段个数 分:单列索引、联合索引(多列)

索引结构描述
B+tree最常见的索引类型,大部分索引都支持B+tree
Hash索引底层的数据结构是哈希表实现,只能精确匹配索引列的查询才有效,不支持范围查询
R-tree空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少
Full-text全文索引是一种通过建立倒排索引快速匹配文档的方式
索引INNODBMyISAMMemory
B+tree支持支持支持
Hash不支持不支持支持
R-tree5.7版本后支持支持不支持
Full-text5.6版本后支持支持不支持

5.索引语法

(1)创建

建表时创建索引:

  CREATE TABLE 表名 ( 属性名 数据类型 [完整性约束条件], ... [UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY [别名] (属性名1[(长度)]  [ASC | DESC]));

(普通索引)

(唯一索引)

直接创建索引:

  CREATE [ UNIQUE | FULLTEXT | SPATIAL ]  INDEX 索引名 ON 表名 (字段名 [ (长度) ] [  ASC | DESC] );

通过 alter table 创建索引

  ALTER  TABLE 表名  ADD  [ UNIQUE | FULLTEXT | SPATIAL ]  INDEX 索引名(字段名 [ (长度) ] [ ASC | DESC]);

(主键索引是特殊的唯一索引)

(2)查看

查看表的创建语句(含索引):show create table table_name\G

查看表结构(含索引简要信息):desc table_name;

查看表的详细索引情况:show index from table_name;

查看SQL执行计划(索引使用情况):desc|Explain select * from table_name where id=1 \G

解释表中数据:

id:代表执行select子句或操作表的顺序;相同时,执行顺序由上至下;不同时,id的序号会递增,id值越大,优先级越高,越先被执行

select_type:查询的类型,主要用于区别普通查询,联合查询,子查询等复杂查询

  (

      simple:简单的 select 查询,查询中不包含子查询或 union 查询

      primary:查询中若包含任何复杂的子部分,最外层查询则被标记为primary

      subquery:在select 或where 列表中包含了子查询

      derived (衍生):在from列表中包含的子查询结果标记为一张虚拟表, mysql会递归这些子查询,把结果放在临时表里也就是derived

      union:第二个select出现在union之后,则被标记为union,若union包含在from子句的子查询中,外层select将被标记为derived

      union result:从union表获取结果的select

  )

table:显示数据是关于哪张表的

partitions:表分区的基本概念。表分区是将大表按规则拆分为多个物理存储单元的技术

type:查询类型从最好到最差依次是→null>system>const>eq_ref>ref>range>index>All,一般情况下,得至少保证达到range级别,最好能达到ref

  (

      null:是不指定表查询显示为null

      system :表中只有一条数据,且存储引擎可以准确的统计到这条数据。system一般出现在MyISAM、memory类型的表查询中,很少用到

      const:根据主键或者唯一索引显示const

      ref:当连接条件使用了非唯一索引时,或者索引列与常量进行比较时显示

      eq_ref:在进行多表连接查询时,表通过主键或唯一索引键进行等值查询

      all:全表扫描

      index:表示用了索引但是还是会遍历整个索引树

      range:当where语句后面出现>或者<或者不等于等的时候会出现

  )

possible_keys:显示可能应用在这张表中的索引,一个或多个,查询到的索引不一定是真正被用到的

key:实际使用的索引,如果为null,则没有使用索引,因此会出现possible_keys列有可能被用到的索引,但是key列为null,表示实际没用索引

key_len:不同类型占用的字节数不同(如 INT 占 4 字节,VARCHAR(10) 可能占 20+ 字节)

  表示索引中使用的字节数,而通过该列计算查询中使用的 索引长度,在不损失精确性的情况下,长度越短越好,key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即,key_len是根据表定义计算而得不是通过表内检索出的

ref:列表示索引查找时所使用的参考值来源

ref值说明示例场景
const主键 /唯一键等值匹配常量WHERE id = 123
table.column跨表列引用JOIN ON a.id = b.user_id
func()函数或表达式结果WHERE YEAR(birthday) = 1990
NULL无外部参考值(索引扫描)WHERE age > 18
const,table.column复合索引部分列使用常量,部分列使用列引用WHERE a=1 AND b=table.c

  理解 ref 值有助于分析查询如何利用索引,优化时应尽量让 ref 使用 const 或表列引用,避免 func() 或复杂表达式,以提升索引效率

rows:根据表统计信息及索引选用情况,大只估算出找到所需的记录所需要读取的行数

filtered:结合 Extra=Using where 时,filtered=100% 表示全表扫描且无有效过滤,filtered=10% 表示仅 10% 行满足条件

Extra:如果是 Using index/where 不需要回表查询,如果是using index condiltion 表示需要回表查询

Table_catalog表目录,逻辑分组的标识默认就是def
table_schema表所属模式(所属数据库)
Table_name表名
Non_unique0表示有,1表示没有
Index_schema索引的数据库
Index_name索引的名称
Seq_in_index索引列数,如果是联合索引显示几列
Collation排序方式A表示升序
cardinality基数,唯一值的估算数量(估计数可能和实际偏差大)
Sub_part是否只索引一部分字符
packed索引列值存储格式是否压缩处理
null字段是否为空
Is_visible是否可见,优化是可见考虑该索引,不可见不考虑
experssion索引基于表达式(支持函数索引类型的库中)

注:

  如果Key是空的, 那么该列值的可以重复, 表示该列没有索引, 或者是一个非唯一的复合索引的非前导列

  如果Key是PRI,  那么该列是主键的组成部分

  如果Key是UNI,  那么该列是一个唯一值索引的第一列(前导列),并别不能含有空值(NULL)

  如果Key是MUL,  那么该列的值可以重复, 该列是一个非唯一索引的前导列(第一列)或者是一个唯一性索引的组成部分但是可以含有空值NULL

(3)删除

  指将表中已经存在的索引删除掉。一些不再使用的索引会降低表的更新速度,影响数据库的性能

删除普通索引:DROP INDEX 索引名 ON 表名;   alter table 表名 drop index 索引名;

删除主键索引:alter table 表名 drop primary key;

6.全文索引

(1)基本概念

  关键字为 fulltext ,用于查找文本中的关键字,基于相似度查询,类似搜索引擎的检索逻辑,而非简单的等值/模糊匹配。

  like + %  适合少量文本的模糊匹配,但若处理大量文本数据,性能会极慢;全文索引在大数据量下检索速度远超  like + % ,但可能存在精度问题

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

  MySQL 中的全文索引,有两个变量,最小搜索长度和最大搜索长度,对于长度小于最小搜索长度和大于最大搜索长度的词语,都不会被索引。通俗点就是说,想对一个词语使用全文索引搜索,那么这个词语的长度必须在以上两个变量的区间内。这两个的默认值可以使用以下命令查看:show variables like '%ft%';

参数解释:

参数名称默认值最小值最大值作用
ft_min_word_len413600MyISAM引擎表创建全文索引最小词和最大词长度
ft_query_expansion_limit2001000MyISAM引擎表使用 查询扩展进行全文搜索的最大匹配数
innodb_ft_min_token_size3016InnoDB 引擎表全文索引包含的最小词长度
innodb_ft_max_token_size841084InnoDB 引擎表全文索引包含的最大词长度

(2)支持情况

版本:

  MySQL 5.6 以前:仅 MyISAM 存储引擎支持;

  MySQL 5.6 及以后:MyISAM 和 InnoDB 存储引擎均支持。

数据类型:仅 char 、 varchar 、 text  及其系列类型可创建全文索引。

(3)创建方式

建表时添加:

修改表结构时添加:

直接添加:

(4)使用语法

  match (col1,col2,...)  against(expr [search_modifier])

可以看到,第一条语句没有结果显示,第二条才有结果,这是因为:

  单词  yo  长度为 2,小于上述参数的默认值(MyISAM 下小于 4,InnoDB 下小于 3),因此不会被全文索引收录,所以查询  match(content) against('yo')  没有结果。

  单词  you  长度为 3,满足 InnoDB 引擎  innodb_ft_min_token_size (默认 3)的要求,会被全文索引收录,因此查询  match(content) against('you')  有结果

7.聚簇索引和非聚簇索引

(1)聚组索引

定义:索引 B+Tree 的叶子节点存储整行数据的主键索引,也称为聚簇索引。它是对磁盘实际数据重新组织以按指定列值排序的算法,数据存储顺序与索引顺序一致。

特点:

  一张表仅允许存在一个聚簇索引,因为数据存储顺序只能有一种。

  主键默认创建聚簇索引,修改聚簇索引实质是修改主键(主键需满足  not null 、 unique )。

InnoDB 自动生成规则:

  有主键时,根据主键创建聚簇索引;

  无主键时,用唯一且不为空的索引列作为聚簇索引;

  若以上都不满足,InnoDB 会创建虚拟聚集索引。

查找过程:以 world  表(主键 id )为例,执行 select * from world where id = 4;  时,直接通过聚簇索引的 B+Tree 叶子节点找到整行数据(运维少年,18)。

(2)非聚族索引(辅助索引,二级索引 )

定义:索引 B+Tree 的叶子节点仅存储键值和索引列的非主键索引,也称为非聚簇索引

特点:

  一个表可存在多个非聚簇索引。

  索引存储与数据存储分离,找到索引后需根据主键回表查询才能获取完整数据

查找过程:以 world  表的 name  辅助索引为例,执行 select name from world where name='张三';  时,先通过非聚簇索引的 B+Tree 找到 张三  对应的主键 id=1 ,再通过聚簇索引回表查询,最终获取数据。

8.乱建索引的后果

  按照业务语句的需求创建合适的索引,并不是将所有列都建立索引:

  每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大

  修改表时,对索引的重构和更新很麻烦,越多的索引,会使表更新变得很浪费时间

  优化器的负担会很重,有可能会影响到优化器的选择

9.索引失效

(1)索引列参与运算或函数操作

  当查询条件中对索引列进行了运算(如算术运算)或函数操作时,索引会失效。例如 SELECT * FROM table WHERE YEAR(create_time) = 2025;  中,对 create_time  列使用 YEAR  函数后,该列的索引将无法被使用。

(2)字符串类型字段未加单引号

  若字段是字符串类型(如 varchar ),查询时未给值加单引号,会导致索引失效。例如 SELECT * FROM t1 WHERE tel=12345678902; (若 tel  是 varchar  类型),因无单引号,索引无法生效;正确写法应为 tel='12345678902'。

(3)模糊查询的首部匹配

  模糊查询中,仅尾部模糊匹配(如 like 'passwd%' )时索引不会失效;若首部模糊匹配(如 like '%passwd' ),索引会失效。

(4)OR连接条件的索引失效

  当 OR  连接的多个条件中,部分列有索引、部分列无索引时,涉及的所有索引都会失效。例如 SELECT * FROM table WHERE idx_col=1 OR no_idx_col=2; ,即使 idx_col  有索引,该查询也会全表扫描。

(5)MySQL数据量评估导致的索引失效

  当 MySQL 评估全表扫描比使用索引更快时(如查询结果包含整张表大部分数据),会放弃使用索引,直接进行全表扫描。例如一张表有 100 万行数据,若查询条件匹配了 80 万行,MySQL 可能选择全表扫描而非使用索引。

(6)示例

  新建表,插入大量数据,通过无索引查询及有索引查询来对比性能

多次执行下述的自我复制,增加数据量(当增加到百万级时,后续查询耗时会变长)

插入新数据,并查询刚插入的数据

查看文件容量:

给 student 表新建索引,发现耗时变长了(0.08 sec)

在有索引的情况下再次查询,(花费时间会少于无索引耗时):

性能提升:

再次查看文件容量,对比建索引前,表容量增大:

总结:索引的本质就是以空间换时间,同时把随机的事件变成顺序的事件,日常项目开发中,读写比例在10:1左右,查询使用频率比较大,虽然损失点存储空间但两害取其轻,还是需要对关键字段新建索引提高查询性能

二、视图

1.视图介绍

   MySQL 中的视图(view)是虚拟表,自身不包含数据,内容由查询定义。

  数据来自定义视图时的基本表,打开视图时动态生成,类似复杂查询的“结果快照”,可节省重复查询的资源。

2.需要视图原因

  解决重复查询问题:例如频繁对  student  和  score  表进行连接查询时,可通过视图封装查询逻辑,避免重复编写语句。

  实现数据安全控制:对敏感数据(如成绩数据),可通过视图隐藏不需要对外暴露的列或行。

3.视图作用和优点

(1)作用

  控制安全:限制用户对数据的访问范围。

  保存查询数据:封装常用的复杂查询逻辑。

(2)优点

  简化操作:用户无需关心底层表的结构、关联和筛选条件,只需关注视图呈现的数据。

  提高数据安全性:可为不同用户定义不同视图,仅开放其允许访问的结果集。

  数据独立:视图结构定义后,底层表新增关系或字段不会影响用户对视图的访问。

4.创建视图

  create [or replace] [algorithm = {undefined | merge | temptable}] view view_name [(column_list)] as select_statement [with [cascaded | local] check option]

说明:
or replace:如果要创建的视图名称已存在,则替换已有视图。

  algorithm:可选参数,表示视图选择的算法,默认算法是 undefined

  undefined:未定义指定算法

  merge:更新视图表数据的同时会更新真实表的数据

  temptable:只能查询不能更新

  view_name:新建的视图名称。

  column_list:可选,表示视图的字段列表。若省略,则使用 select 语句中的字段列表。

  as select_statement:创建视图的 select 语句。

  with check option:表示更新视图时要保证该视图的 where 子句为真。

总结:适用场景根据当前视图创建另一个视图时:

  with local  check option(只检查当前条件)

  with cascaded check option(检查当前以及上一级的条件)

  with check option(所有的条件都检查)

5.创建视图限制

(1)列名限制

  不能使用 select * 语法来选择所有列。必须明确指定要选择的列,这样可以确保视图的结构清晰,并且在基表结构发生变化时,视图的定义不会受到意外影响。

  列名必须是唯一的,不能有重复的列名。如果在 select 语句中使用了表达式或函数生成列,需要为其指定一个唯一的别名作为列名。(子查询需要更改列名)

(2)数据类型限制

  视图中选择的列的数据类型通常不能进行随意转换或修改。如果基表中的列数据类型发生变化,可能会影响视图的查询结果或导致视图无法正常使用。

  某些数据类型可能不适合在视图中使用,例如大对象数据类型(如BLOB、CLOB等),在视图中使用可能会导致性能问题或其他复杂性。

(3)查询语句限制

  不能使用ORDER BY除非结合LIMIT

  通常情况下,视图定义中的 select 语句不允许使用 order by 子句。因为视图本质上是一个虚拟表,排序操作应该在查询视图时进行。不过,如果 order by 与 limit 一起使用,MySQL 是允许的(有意义的)。

  视图(View)定义里存在 order by 子句,而查询该视图的 SQL 语句里同样有 order by 子句时,最终的排序结果是由查询语句中的 order by 子句来决定的。

错误代码示例:

  create view vw_employees as

  select employee_id, first_name, last_name

  from employees

  order by employee_id;

正确代码示例:

  create view vw_employees_limit as

  select employee_id, first_name, last_name

  from employees

  order by employee_id

  limit 10;

不能使用 group by子句,这些子句用于在查询结果中进行分组计算,不适合在视图定义中使用。

当使用连接查询来定义视图时,连接条件必须是明确和有效的,不能使用自连接或复杂的交叉连接方式,除非有明确的业务需求。

(4)权限限制

  用户创建视图时,必须对 select 语句中引用的所有表或视图具有适当的查询权限。如果没有足够的权限,将无法成功创建视图。

  视图的权限管理与基表是相互独立的。创建视图后,需要单独为用户或角色授予对视图的访问权限,即使用户对基表有访问权限,也不一定能够访问视图,反之亦然。

  这些限制有助于确保视图的稳定性、性能和数据一致性,同时也遵循了视图作为一种数据抽象和查询工具的设计原则。不同的数据库管理系统可能会对视图的 select 语句有一些细微的差异和特定的限制,具体使用时需要参考相应的数据库文档

示例:

创建来源1张表的视图:

创建多表连接的视图:

创建视图,字段起别名:

6.更新视图

  更新视图中的数据,实际上是更新创建视图时用到的基本表中的数据

以下视图不可更新:

  包含以下关键字的 SQL 语句:聚合函数、distinct、group by 、having、union 或 uinon all

  select 中包含子查询

  from 一个不可更新的视图

  where 子句的子查询引用了 from 子句中的表

示例:

视图中聚合函数不可更新:

对分组和having字段不可更新:

7.修改视图

示例:

通过 create or replace view 命令修改视图:

通过 alter view 命令修改视图:

8.删除视图

  drop view [if exists] view_name;

示例:

9.导致视图表数据异常的行为

(1)视图本身并不存储数据,其数据来源于基表

(2)权限变更--没有查询权限

(3)基表数据类型变更

10.视图使用规则总结

  视图必须有唯一命名

  在mysql中视图的数量没有限制

  创建视图必须从管理员那里获得必要的权限

  视图支持嵌套,也就是说可以利用其他视图检索出来的数据创建新的视图

  在视图中可以使用order by,但是如果视图内已经使用该排序子句,则视图的order by将覆盖前面的order by。

  视图不能索引,也不能关联触发器或默认值

  视图可以和表同时使用

http://www.dtcms.com/a/398128.html

相关文章:

  • 【C++无数组矩阵对角线平均值保留2位小数】2022-11-18
  • 阿里巴巴网站费用怎么做分录烟台企业展厅设计
  • ZooKeeper与Kafka分布式协调系统实战指南:从基础原理到集群部署
  • lesson66:JavaScript BOM与DOM全解析:从基础到现代前端实践引言:前端开发的两大基石
  • UNIAPP如何自定义全局方法?
  • 040 线程控制
  • 前端开发利器:nvm、npm与pnpm全面解析与TypeScript/JavaScript选择指南
  • 电影网站如何做seo哪家网站建设公司好
  • LeetCode 刷题【90. 子集 II】
  • Spring Boot启动报错:Failed to configure a DataSource 全面解析与解决方案
  • MongoDB源码delete分析观察者getOpObserver()->onDelete
  • 企业网站模板htmlwordpress cos 配置
  • ACL 2025 Time-LlaMA 大语言模型高效适配时间序列预测
  • 2025开发者云服务器评测:AWS, Vercel, Railway该如何选?
  • 金融数据库--下载全市场股票日线行情数据
  • HTML `<meter>` 标签:原生度量衡指示器,直观展示百分比、评分等量化数据
  • 平安养老险广西分公司 | 开展金融知识公益宣教活动
  • 威海北京网站建设怎么做网站推广世界杯
  • php的网站模板下载如何修改自己的网站标题
  • VS Code 格式化配置优先级与作用机制(不含ESlint)
  • python+springboot+uniapp微信小程序“美好食荐”系统 美食推荐 菜谱展示 用户互动 评论收藏系统
  • 微信小程序页面滚动到指定位置
  • 抢占2025SEO先机:九大趋势洞察与实战行动路线图
  • Ubuntu 安装 Maven 私服 Nexus
  • maven install和package 有什么区别
  • 关于maven编译没把resources资源包含进target目录
  • 网站开发文档合同wap712c
  • [Maven 基础课程]11_Windows 安装 Maven 私服 Nexus
  • LinuxC++项目开发日志——基于正倒排索引的boost搜索引擎(3——通过cppjieba库建立索引模块)
  • 早报库|深圳奔向全球“消费级3D打印第一城”;苹果持续扩招增材制造人才;乌军前线大量使用3D打印地雷