MySQL中的索引

文章目录

一、索引

MySQL官方对索引I的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。

索引的本质:索引是数据结构。可以简单理解为"排好序的快速查找数据结构",满足特定查找算法。这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法。

数据库的索引好比是一本书的目录,能加快数据库的查询速度。

  • 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往是存储在磁盘上的文件中的(可能存储在单独的索引文件中,也可能和数据一起存储在数据文件中)。

索引底层的数据结构存在很多类型,常见的有:B树、B+树和哈希。在MySQL中,无论是Innodb还是MyIsan都使用了B+树作为索引结构。

MySQL的索引和数据就是位于存储引擎中。MySQL 创建索引的基本结构,其中的参数说明如下:

sql 复制代码
CREATE TABLE table_name (
    col_name data_type,
    ...
    [UNIQUE | FULLTEXT ] [INDEX | KEY] [index_name] (col_name [length]) [ASC | DESC],
    ...
);

参数解释:

  • UNIQUE:可选参数,表示唯一索引,确保索引列中的所有值是唯一的。
  • FULLTEXT :可选参数,表示全文索引,用于加速文本字段的搜索(适用于 InnoDB 和 MyISAM 存储引擎的 CHARVARCHARTEXT 列)。
  • INDEX | KEYINDEXKEY 是同义词,用于指定创建索引的关键字。
  • index_name:指定索引的名称(可选)。如果不指定,MySQL 默认使用列名作为索引名。
  • col_name:索引的列名,必须是表中定义的列。
  • length:可选参数,用于指定索引的长度(仅对字符串类型的字段有效)。部分索引可以节省存储空间并提高查询速度。
  • ASC | DESC:指定索引值的排序顺序(升序或降序)。在 MySQL 中,B+Tree 索引默认使用升序排序,但排序顺序在大多数情况下对查询优化影响不大。

例如,创建一个具有唯一索引和全文索引的表语句如下:

sql 复制代码
CREATE TABLE example_table (
    id INT,
    name VARCHAR(100),
    description TEXT,
    UNIQUE INDEX unique_name_index (name),
    FULLTEXT INDEX description_text_index (description)
);

二、索引分类

可以按照四个角度来分类索引。

  • 按数据结构分类:B+tree索引、Hash索引、全文索引
  • 物理实现 分类:聚簇索引(主键索引)、二级索引(辅助索引)
  • 功能逻辑 分类:普通索引、唯一索引、主键索引、前缀索引
  • 字段个数 分类:单列索引、联合索引

1、按物理存储分类

按照物理实现,索引分为聚簇索引和非聚簇索引(也称二级索引或辅助索引)。

a.聚簇索引

**所有的用户数据都存在了叶子节点,数据即索引,索引即数据。**聚簇索引将数据存储与索引结构结合在一起,索引的叶子节点即存储了数据行的全部信息。这意味着通过聚簇索引查询到的索引项就等于查询到完整的数据行,无需额外访问。

使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:

  • 页内的记录是按照主键的大小顺序排成一个单向链表。
  • 各个存放用户记录的页也是根据页中用户记录的主键大小顺序排除一个双向链表。存放目录项记录的页分为不同层次,在同一层次中的页是根据页中目录项记录的主键大小顺序拍成的一个双向链表。

在 InnoDB 中,如果表定义了主键,系统会自动将主键列作为聚簇索引的索引键;如果没有主键,则会选择第一个非空的唯一列;如果没有符合条件的唯一列,系统会创建一个隐式的自增 rowid 列作为聚簇索引键。

唯一性:每个表只能有一个聚簇索引,因为数据只能按照一种顺序存储在物理结构中。

B+树的叶子节点存储的完整的用户数据。

优点

数据访问更快:因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快。

聚簇索引对于主键的排序查找和范围查找速度非常快:数据按照聚簇索引的顺序存储,范围查询时只需顺序读取数据页。查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以节省了大量的io操作。

缺点

插入速度严重依赖于插入顺序:按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于Inn哦DB表,我们一般都会定义一个自增的ID列为主键。

更新主键的代价高:因为将会导致被更新的行移动。

占用较大存储空间:聚簇索引存储的是完整数据行,索引结构占用更多空间。

更新和插入开销较大:由于聚簇索引将数据存储顺序固定为主键顺序,插入新数据或更新主键时可能需要重新组织数据页,影响性能。

sql 复制代码
-- 创建一个带有主键的表
CREATE TABLE employees (
    employee_id INT PRIMARY KEY,  -- 主键作为聚簇索引
    name VARCHAR(50),
    department_id INT
);

在此表中,employee_id 列作为主键,因此 employee_id 成为聚簇索引的键,数据存储会按照该列的顺序排列。

b.二级索引

二级索引 (Secondary Index),也称为辅助索引非聚簇索引,与聚簇索引不同,其叶子节点存储的并不是完整的数据行,而是指向聚簇索引中数据的位置。

索引中数据的位置。

  1. 独立于数据存储顺序:二级索引的键值与数据的物理存储顺序无关,它仅用于加速对特定列的查询操作。
  2. 叶子节点存储指向聚簇索引的指针:在 InnoDB 中,二级索引的叶子节点包含聚簇索引键的值,而不是完整的数据行。因此,通过二级索引查找数据时,先通过索引定位到聚簇索引键,再访问聚簇索引以获取完整数据行。
  3. 允许多个二级索引:一个表可以有多个二级索引,每个索引加速不同列上的查询。

优点

  • 查询优化 :适用于加速非主键列上的查询,尤其是在 WHEREORDER BYGROUP BY 操作中。
  • 灵活性高:可以根据不同查询需求添加多个二级索引。

缺点

  • 访问成本较高:查询时需要先定位聚簇索引,再通过聚簇索引找到完整数据,称为"回表"操作。
  • 维护成本:插入、更新和删除数据时,需要同时维护二级索引,影响写操作的性能。
sql 复制代码
-- 创建一个表,带有二级索引
CREATE TABLE employees (
    employee_id INT PRIMARY KEY,
    name VARCHAR(50),
    department_id INT,
    INDEX idx_department (department_id)  -- 二级索引
);

在此示例中,department_id 列上创建的 idx_department 是二级索引。通过 department_id 查询时,MySQL 首先通过 idx_department 索引找到对应的主键值,然后再查找聚簇索引以获取完整的数据行。

回表:

在查询时使用了二级索引,如果查询的数据能在二级索引里查询的到,那么就不需要回表,这个过程就是覆盖索引。如果查询的数据不在二级索引里,就会先检索二级索引,找到对应的叶子节点,获取到主键值后,然后再检索主键索引,就能查询到数据了,这个过程就是回表。

回表是为了控制非聚簇索引的大小,如果非聚簇索引直接存储数据,所有索引都会包含相同的数据,这会导致大量的数据冗余。每个索引都需要重复存储相同的行数据,浪费大量的存储空间。

c.聚簇索引和二级索引的对比

特点 聚簇索引 二级索引
数据存储方式 索引和数据存储在一起 仅存储指向聚簇索引的指针
数据访问效率 查询效率高,不需要回表 需要回表操作,查询速度稍慢
索引数量限制 每张表只能有一个 可在表上创建多个
更新和插入性能 插入和更新成本高,可能需要重新排列数据页 维护多个二级索引增加写入开销
适用场景 主键查询和范围查询 非主键列的查询
  • 聚簇索引将数据存储与索引结合,查询主键时效率更高,适合范围查询。
  • 二级索引独立于数据的存储顺序,为非主键列加速查询,适用于多样化的查询需求,但访问数据时可能需要回表操作。

2、按数据结构分类

从数据结构的角度来看,MySQL 常见索引有 B+Tree 索引、HASH 索引、全文索引。

B+Tree 是 MySQL 中使用最广泛的索引类型,适用于 InnoDB 和 MyISAM 等常见存储引擎。

索引类型 InnoDB MyISAM
B+Tree索引
Hash索引
全文索引

在创建表时,InnoDB 存储引擎根据不同情况选择列作为聚簇索引的键(key):

  • 如果表有主键,则默认使用主键作为聚簇索引的键;
  • 若没有主键,则选择第一个不包含 NULL 值的唯一列作为聚簇索引的键;
  • 如果既没有主键,也没有不含 NULL 值的唯一列,InnoDB 会自动生成一个隐式自增 id 列作为聚簇索引的键。

除了聚簇索引,其他索引被称为辅助索引(二级索引或非聚簇索引)。InnoDB 中的主键索引和二级索引默认使用 B+Tree 索引

  • B+树索引:只有叶子节点存储 value,非叶子节点只有指针和 key。
  • 哈希索引:类似键值对的形式,一次即可定位。
  • 全文索引 :对文本的内容进行分词,进行搜索。目前只有 CHARVARCHARTEXT 列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。

a.Hash索引

哈希表是键值对的集合,通过键即可快速取出对应的值,因此哈希表可以快速检索数据(接近 O(1))。

Hash索引基于Hash表实现,只有查询条件精确匹配Hash索引中的列时,才能够使用到hash索引。对于Hash索引中的所有列,存储引擎会为每行计算一个hashcode,Hash索引中存储的就是hashcode。

通过哈希算法(也叫散列算法),我们可以快速找到 key 对应的 index,找到了 index 也就找到了对应的 value。

c++ 复制代码
hashcode = hashfunc(key);
index = hash % arr.size();

例如一个维护了卡号和姓名的表,根据卡号查询名字,其Hash索引如下:

但是,哈希算法存在Hash冲突问题,也就是说多个不同的 key 最后得到的 index 相同。通常情况下,我们常用的解决办法是 链地址法。链地址法就是将哈希冲突数据存放在链表中。

为了减少 Hash 冲突的发生,一个好的哈希函数应该"均匀地"将数据分布在整个可能的哈希值集合中。

HASH索引|可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但只在"="和"in"条件下才高效,对于范围查询、排序以组合索引仍然效率不高。

由于存储的值不一定是递增的,这样在新增数据时,只需要在后面追加。因此在范围查询的时候查询速度很慢。

但由于 Hash 索引不支持顺序和范围查询。假如我们要对表中的数据进行排序或者进行范围查询,那 Hash 索引可就不行了。并且,每次 IO 只能取一个。

b.全文索引

全文索引是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。全文索引非常适合大型数据集,对于小的数据集,它的用处比较小。

使用参数FULLTEXT可以设置索引为全文索引。在定义索引的列上支持值的全文查找,允许在这些索引引列中插入重复值和空值。全文索引只能创建在CHARVARCHARTEXT类型及其系列类型的字段上,查询数据量较大的字符串类型的字段时,使用全文素引可以提高查询速度。例如,表student的字段informationTEXT类型,该字段包含了很多文字信息。在字段information上建立全文索引后,可以提高查询字段information的速度。

c.B+树索引

B+树索引是一种基于 B+树数据结构实现的索引类型,是 MySQL 默认采用的索引结构。MySQL 中的 InnoDB 存储引擎默认采用 B+树作为聚簇索引结构。

B+Tree 的主要特点及其在数据库中的重要性:

  1. 多路平衡树:B+Tree 是一种多路平衡树,每个节点可以包含多个元素和子节点,从而减少树的深度,加快查找速度。
  2. 叶子节点链表:所有叶子节点形成一个双向链表结构,相邻的叶子节点相互连接,便于范围查询。查询数据时可以顺序遍历叶子节点,减少磁盘访问次数。
  3. 路径平衡:B+Tree 的根节点到叶子节点路径长度相同,保持了树的平衡性,从而提高了查询效率。

B+树全称:多路平衡搜索树,减少磁盘访问次数;用来组织磁盘数据,以页为单位,物理磁盘页一般为4K,innodb 默认页大小为 16K;对页的访问是一次磁盘io,缓存中会缓存常访问的页;

非叶子节点只存储索引信息,叶子节点存储具体数据信息。叶子节点之间互相连接,方便范围查询。

在 InnoDB 中,默认的 B+树节点大小为 16 KB。这意味着每个节点(无论是叶子节点还是非叶子节点)都可以存储最多 16 KB 的数据。对于 B+树中的非叶子节点,每个节点存储的是键值和指向下一个节点的指针。而在叶子节点中,存储的是数据记录。

我们假定:每个键值大小为10字节,指针大小为6字节,每一行大小为1KB,每个节点大小为16KB。

一个非叶子节点存储的内容为一组键值(key)和指向下一个节点的指针(pointer)。每个非叶子节点存储的键值和指针总共占用 10 字节(key)+ 6 字节(pointer)= 16 字节。

因此,在 16 KB 的节点大小限制下,一个非叶子节点最多可以存储:

scss 复制代码
16 KB / 16 字节 = 1024 个 (key + pointer)

每个叶子节点存储的是数据行,每一行数据的大小为 1 KB。由于每个叶子节点的大小为 16 KB,所以每个叶子节点最多可以存储:

scss 复制代码
16 KB / 1 KB = 16 行数据

但是在实际情况中,存储的行数可以更高,因为不仅仅是存储数据行,还可能有其他元数据(如指向下一个叶子节点的指针),所以每个叶子节点能存储的行数会更多。假设每个叶子节点能够存储 1024 行数据。

根据上面的计算,我们可以通过 B+树的层数来估算最大存储能力。

2 层 B+树

  • 根节点:一个非叶子节点可以存储 1024 个键值和指针;
  • 叶子节点:每个叶子节点可以存储 1024 行数据。

因此,2 层 B+树的总记录数为:

yaml 复制代码
1024 * 16 = 16384 条记录

3 层 B+树

  • 根节点:可以存储 1024 个键值和指针;
  • 第二层节点:可以存储 1024 个指向叶子节点的指针;
  • 叶子节点:每个叶子节点可以存储 1024 行数据。

因此,3 层 B+树的总记录数为:

yaml 复制代码
1024 * 1024 * 16 = 1677 7216 条记录

4 层 B+树

  • 根节点:可以存储 1024 个键值和指针;
  • 第二层节点:可以存储 1024 个指向第三层节点的指针;
  • 第三层节点:可以存储 1024 个指向叶子节点的指针;
  • 叶子节点:每个叶子节点可以存储 1024 行数据。

因此,4 层 B+树的总记录数为:

yaml 复制代码
1024 * 1024 * 1024 * 16 = 171 7986 9184 条记录

数据库的索引和数据都是存储在硬盘的,我们可以把读取一个节点当作一次磁盘 I/O 操作。那么上面的整个查询过程一共经历了 3 个节点,也就是进行了 3 次 I/O 操作。

B+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,这意味着从千万级的表查询目标数据最多需要 3-4 次磁盘 I/O,所以B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率很高,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4次

d.小结

B+树与 B 树的区别

  • 数据存储
    • B 树:在 B 树中,非叶子节点除了存储指针外,还存储数据。也就是说,B 树的每个节点都包含了完整的键值和对应的数据记录。
    • B+树:与 B 树不同,B+树的非叶子节点仅存储键值和指向子节点的指针,而数据只存储在叶子节点。由于叶子节点只存储数据,这样可以使得非叶子节点的存储容量更大,从而减少树的高度,提高查询效率。
  • 单节点的数据量
    • B+树:由于非叶子节点不存储数据,单个节点的存储容量更大。因此,在相同的磁盘 I/O 次数下,B+树能够查询更多的节点。
    • B 树:每个非叶子节点都需要存储数据,因此每个节点的存储量较小,导致树的高度可能更高,查询效率较低。

B+树的叶子节点双向链表

B+树的叶子节点之间通过双向链表连接,这使得 B+树非常适合范围查询。例如,使用 BETWEEN>< 等范围查询时,查询开始后可以通过叶子节点的链表顺序访问相邻的叶子节点,极大提高了范围查询的效率。

B 树没有类似的结构,其叶子节点没有双向链表,因此无法像 B+树那样高效地进行顺序查找。

B+树与二叉树的对比

  • 二叉树 的每个节点最多有两个子节点,因此其搜索的复杂度为 O(logN),在处理大量数据时,搜索过程中的磁盘 I/O 次数更多,查询效率较低。
  • B+树的每个节点有更多的子节点,因此它的搜索复杂度较低,树的高度较小,查询过程中磁盘 I/O 次数较少,性能更高。

B+树与哈希表的对比

  • 哈希表 :哈希表在进行等值查询时的效率非常高,搜索复杂度为 O(1)。哈希表适用于快速的等值查找,但对于范围查询则无能为力,因为哈希表的存储方式不保持元素的顺序。
  • B+树 :与哈希表不同,B+树不仅支持等值查询(如 =IN),还支持范围查询(如 BETWEEN><)。因此,B+树索引适用于更加广泛的场景,尤其是在需要处理范围查询和排序操作时,B+树的性能远优于哈希表。

B+树:适用于需要高效的范围查询、排序以及频繁的插入/删除操作的场景。例如,在数据库中,B+树通常用作索引结构来处理这些操作。

哈希表:适用于快速的等值查询(如精确匹配)场景,但不适合范围查询或排序。

B+树的结构非常适合用作数据库索引,特别是在处理大规模数据时,能够提供较低的树高,减少磁盘 I/O 次数,从而提高查询效率。

哈希表适合进行快速的等值查询,但不支持范围查询,因此它在数据库索引中应用有限。

B+树的双向链表结构和较低的树高,使得它在需要高效查询、排序和范围查询的场景中比 B 树、二叉树和哈希表更具优势。

通过这些特性,B+树在 MySQL 等数据库系统中成为了默认的索引结构,帮助数据库实现高效的数据存储和检索。

3、按功能逻辑分类

从功能逻辑的角度来看,索引分为普通索引、唯一索引、主键索引、前缀索引。

a.普通索引

在创建普通索引时,不附加任何限制条件,只是用于提高查询效率。这类索引可以创建在任何数据类型中,其值是否唯一和非空,要由字段本身的完整性约束条件决定。建立索引以后,可以通过索引进行查询。例如,在表student的字段name上建立一个普通索引,查询记录时就可以根据该索引进行查询。

sql 复制代码
-- 在创建表时添加普通索引
CREATE TABLE employees (
    id INT,
    name VARCHAR(50),
    department_id INT,
    INDEX idx_department_id (department_id)  -- 普通索引
);

-- 在已存在的表上添加普通索引
CREATE INDEX idx_name ON employees(name);

创建普通索引后,MySQL 会在执行涉及索引列的查询时自动利用索引,显著提升数据检索的效率。

普通索引通常用于需要快速查找或频繁查询的数据列。例如,频繁用于 WHERE 子句筛选的列或排序操作的列,通常适合添加普通索引。

b.唯一索引

使用UNIQUE参数可以设置索引为唯一性索引,在创建唯一性索引时,限制该索引的值必须是唯一的,但允许有空值。在一张数据表里可以有多个唯一索引。

凡是声明了唯一性约束的字段,自动添加了唯一索引。

例如,在表student的字段email中创建唯一性索引,那么字段email的值就必须是唯一的。通过唯一性索引,可以更快速地确定某条记录。

c.主键索引

主键索引I就是一种特殊的唯一性索引,在唯一索引的基础上增加了不为空的约束,也就是NOT NULL+ UNIQUE,一张表里最多只有一个主键索引。这是由主键索引的物理实现方式决定的,因为数据存储在文件中只能按照一种顺序进行存储。

sql 复制代码
# 创建
CREATE TABLE student (
    id INT(10) UNSIGNED  AUTO_INCREMENT ,
    student_no VARCHAR(200),
    student_name VARCHAR(200),
    PRIMARY KEY(id) 
);
# 删除
ALTER TABLE student drop PRIMARY KEY ;  

修改主键索引时,必须先删除掉原索引,再新建索引。

d.前缀索引

前缀索引 是一种节省空间的索引方式,主要用于长文本或字符串列。创建索引时,前缀索引只索引字段值的前部分字符,而不是整个字段值。这种方式可以显著减少索引的存储空间,并在查询大量数据时提升性能,适用于文本类型字段(例如 CHARVARCHARTEXT)。

假设我们有一张用户信息表 users,其中包含一个 email 字段。由于 email 字段可能较长,因此可以对其创建前缀索引来加速查询。

sql 复制代码
CREATE TABLE users (
    id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(255)
);

-- 创建一个长度为 10 的前缀索引
CREATE INDEX idx_email ON users(email(10));

在这个示例中,我们只对 email 字段的前 10 个字符建立索引。这样在查询类似 email LIKE 'user@example.com%' 的数据时,可以使用该索引加快查询速度。

4、按字段个数逻辑分类

a.单列索引

在表中的单个字段上创建索引。单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段即可。一个表可以有多个单列索引。

b.联合索引

联合索引是在表的多个字段组合上创建一个索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询,但是只有查询条件中使用了这些字段中的第一个字段时才会被使用。例如,在表中的字段idnamegender上建立一个多列索引idx_id_name_gender,只有在查询条件中使用了字段id时该索引才会被使用。使用组合索引时遵循最左前缀集合


三、索引常见面试题

InnoDB与MyISAM索引实现的区别

  1. MyISAM的索引方式都是非聚簇索引,而InnoDB包含一个聚簇索引。

也就是说,InnoDB中我们只需要根据主键值对聚簇索引进行一次查找就能找到记录,而MyISAM却需要进行一次回表操作。

  1. InnoDB的数据文件本身就是索引文件,而MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。

MyISAM的表在磁盘上存储在以下文件中:*.sdi(描述表结构)、*.MYD(数据),.MYI(索引)。

InnoDB的表在磁盘上存储在以下文件中:.ibd(表结构+索引+数据都存储在一起)。数据和索引存储在同一个结构中,所有的数据存储都按照主键顺序进行。

  1. InnoDB的非聚簇索引Idata域存储相应记录主键的值,而MyISAM索引记录的是地址。

MyISAM的叶子节点中存储的键值为索引列的值,数据为索引所在行的磁盘地址。数据存储在单独的文件中,查询数据时通过索引找到数据文件的物理位置。

InnoDB的聚簇索引的叶子节点存储的是数据行本身。非聚簇索引的叶子节点存储的是主键值,而不是数据行。当通过二级索引查找数据时,必须通过主键再去访问数据。

因此MyISAM的回表速度是很快的,直接拿着地址偏移量到文件中取数据。而Innodb是通过获取主键之后再去聚簇索引中查找。

面试题:为什么 InnoDB 要使用 B+ 树作为索引?

  • 更高效的磁盘 IO,因为它减少了磁盘寻道时间和页的加载次数

  • 支持范围查询,与 B 树相比,B+ 树的叶子结点通过指针连接成一个链表,这使得查询范围变得非常高效。在 B+ 树上执行范围查询可以简单地从范围的起始点开始,然后沿着链表向后遍历,直到结束点。

  • 查询性能稳定,B+ 树的所有查找操作都要查到叶子节点,这使得所有的查询操作都有着相同的访问深度,因此查询性能非常稳定。不像某些其他数据结构,如 B 树,其查询性能因为数据存在所有的节点上导致深度不一致,性能不稳定。

面试题:索引是不是建的越多越好?

不是。

  • 索引会占据磁盘空间
  • 每当在表中插入、删除或更新数据时,数据库系统都需要更新所有相关的索引。

面试题:索引不适合哪些场景呢?

  • 数据表很小:如果数据表的记录数量非常少,数据库进行全表扫描的成本可能比维护和查询索引的成本要低。在这种情况下,索引可能不会带来性能提升。
  • 频繁更新的索引列:如果一个列的值经常更改,每次更改都可能导致索引的重建或重排,这可以增加大量的性能负担。

面试题:索引在哪些情况下会失效?

  • 非最左前缀使用 :大多数数据库的索引(特别是符合索引)是基于最最左前缀原则构建的。如果查询不从索引的最左列开始,索引可能不会被使用。例如,索引是在 (lastname, firstname) 上,但查询只有关于 firstname 的条件
  • 使用 LIKE 运算符时的前导通配符 :如果查询使用 LIKE 且模式以通配符开始(如 LIKE '%Smith'),则索引可能不能使用,因为数据库无法利用索引有效地查找这种模式。
  • 数据类型不匹配 :如果查询条件中的数据类型与索引列的数据类型不匹配,数据库可能需要进行隐式类型转换,这可能导致索引失效。例如,如果索引列是整数类型,但查询条件用字符串来比较,如WHERE column = '123'
  • NULL:某些数据库处理包含 NULL 值的列的索引时可能会有问题。如果索引列有很多 NULL 值,或者查询条件包含对 NULL 值的比较,索引的效果可能会降低。
  • OR 条件 :使用OR连接的查询条件如果不是每个条件都在同一个索引中,可能导致索引失效。例如,如果有两个条件分别使用不同的索引,数据库可能决定放弃使用索引。
  • 使用不等式运算符 :虽然索引可以用于不等式查询(如><等),但如果这样的查询返回表中大部分数据,数据库优化器可能决定全表扫描更有效,因此不使用索引。
    **:如果查询使用 LIKE 且模式以通配符开始(如 LIKE '%Smith'),则索引可能不能使用,因为数据库无法利用索引有效地查找这种模式。
  • 数据类型不匹配 :如果查询条件中的数据类型与索引列的数据类型不匹配,数据库可能需要进行隐式类型转换,这可能导致索引失效。例如,如果索引列是整数类型,但查询条件用字符串来比较,如WHERE column = '123'
  • NULL:某些数据库处理包含 NULL 值的列的索引时可能会有问题。如果索引列有很多 NULL 值,或者查询条件包含对 NULL 值的比较,索引的效果可能会降低。
  • OR 条件 :使用OR连接的查询条件如果不是每个条件都在同一个索引中,可能导致索引失效。例如,如果有两个条件分别使用不同的索引,数据库可能决定放弃使用索引。
  • 使用不等式运算符 :虽然索引可以用于不等式查询(如><等),但如果这样的查询返回表中大部分数据,数据库优化器可能决定全表扫描更有效,因此不使用索引。
  • 排序和聚合操作 :如果查询包括排序(ORDER BY)或聚合(如GROUP BYMAX()COUNT()等)操作,且这些操作所涉及的列没有相应的索引支持,那么执行这些操作时索引可能不被使用。
相关推荐
难以触及的高度7 分钟前
mysql中between and怎么用
数据库·mysql
Jacky(易小天)21 分钟前
MongoDB比较查询操作符中英对照表及实例详解
数据库·mongodb·typescript·比较操作符
Karoku0661 小时前
【企业级分布式系统】ELK优化
运维·服务器·数据库·elk·elasticsearch
小技与小术2 小时前
数据库表设计范式
数据库·mysql
安迁岚2 小时前
【SQL Server】华中农业大学空间数据库实验报告 实验三 数据操作
运维·服务器·数据库·sql·mysql
安迁岚2 小时前
【SQL Server】华中农业大学空间数据库实验报告 实验九 触发器
数据库·sql·mysql·oracle·实验报告
Loganer2 小时前
MongoDB分片集群搭建
数据库·mongodb
LKID体2 小时前
Python操作neo4j库py2neo使用之创建和查询(二)
数据库·python·neo4j
刘大浪3 小时前
后端数据增删改查基于Springboot+mybatis mysql 时间根据当时时间自动填充,数据库连接查询不一致,mysql数据库连接不好用
数据库·spring boot·mybatis
一只爱撸猫的程序猿3 小时前
简单实现一个系统升级过程中的数据平滑迁移的场景实例
数据库·spring boot·程序员