在 MySQL 中,索引是一种特殊的数据结构,用于提高数据库查询的速度和效率。MySQL 支持多种不同类型的索引,以下是 MySQL 中常用的索引类型:
主键索引(Primary Key Index):一种唯一性索引,用于快速查询表中的主键列。每张表只能有一个主键索引。
唯一索引(Unique Index):保证索引列的唯一性,用于快速查询满足某一条件的唯一性记录。一个表可以有多个唯一索引。
全文索引(Fulltext Index):专门用于对内容进行搜索的索引,例如文章、评论等的内容。MySQL 中只有 MyISAM 和 InnoDB 引擎支持全文索引。
组合索引(Composite Index):包含多个列的索引,可以提高多列的查询效率。
空间索引(Spatial Index):专门用于空间数据类型的索引,如 Point、LineString、Polygon 等。MySQL 中只有 MyISAM 和 InnoDB 引擎支持空间索引。
普通索引(Normal Index):最常用的一种索引类型,它们可以应用于表中的任何列,包括 NULL 和重复值。
除了以上的索引类型之外,MySQL 还支持前缀索引、覆盖索引、隐藏列索引等,不同类型的索引有不同的适用场景和使用方式。为了保证数据库的性能和稳定性,需要根据具体的业务场景和需求进行相应的优化和调整。
常用的索引类型在 MySQL 中的创建方式有两种形式:在创建表时创建索引和在已经存在的表中添加索引。
在创建表时创建索引:
CREATE TABLE t ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20), age INT, INDEX name_age (name, age) );
在上述代码中,我们创建了一个名为 t 的表,包括三个字段 id、name 和 age,其中 id 为主键索引列,name 和 age 通过组合索引(Composite Index)的方式建立了一个索引 name_age。
在已经存在的表中添加索引:
ALTER TABLE t ADD INDEX name_age (name, age);
在上述代码中,我们对名为 t 的表添加了一个索引 name_age。
创建唯一索引:
CREATE TABLE t ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20) NOT NULL, age INT, UNIQUE INDEX name_unique (name) );
ALTER TABLE t ADD UNIQUE INDEX name_unique (name);
唯一索引和普通索引的最大区别在于约束条件和数据的唯一性,这也是它们的效果颇有差异的。
唯一索引:
唯一索引是强制性索引,保证了所在列的值的唯一性,可以防止重复的数据插入、更新或删除,且每个索引列的值都是唯一的。因此,唯一索引用来保障数据表中某列的唯一性,一张表可以有多个唯一索引,但一个索引列上只有一个唯一索引。
唯一索引可以用来优化较高的查询效率,因为使用索引查询比使用非索引查询要更快。同时,唯一索引也会带来一定的写入性能代价,因为 MySQL 必须保证索引的唯一性而进行额外的检查。
普通索引:
普通索引是SQL表的常规索引,它们可以应用于表中的任何列,包括 NULL 和重复值。它们并不强制唯一性,这意味着可以创建多个包含重复值的普通索引,并且插入、更新、删除也不会涉及到额外的性能代价。在 SQL 查询时,使用普通索引仅仅是简单地按照索引列的值排序返回结果。
因此,普通索引通常用于那些经常进行搜索和排序的列,但是它并未强制保证某列的值唯一。
如果需要根据唯一的字段操作数据库,推荐使用唯一索引。唯一索引可以保证该列的值的唯一性,并且可以帮助加速 SELECT、UPDATE 和 DELETE 操作的执行。而普通索引通常用于搜索和排序非唯一性的字段。
对于一些需要快速定位数据的业务场景,唯一索引可以帮助我们快速地通过唯一键查找到对应的数据行。因为唯一索引会将唯一值和对应的ROWID关联起来,通过 B-Tree 或 Hash 算法,可以快速地定位需要查找的行。因此,使用唯一索引可以显著提高数据的查找速度和查询效率。
如果一个字段,只有4种值,如1,2,3,4,并且大部分记录的值会是4,那么应该给这个字段设置索引吗
如果一个字段只有4种固定的值,而且大多数记录的值都是相同的,那么在这种情况下,不建议为这个字段建立索引。因为如果该字段的唯一性不高,那么即使在该字段上建立索引,由于符合索引条件的数据过多,使用该索引仍然需要扫描大量的数据块,以至于效率并不会有太大的提升。
针对这个字段的查询,查询1,2,3的情况会比较多,这种情况下,应该设置索引吗
如果针对这个字段的查询以查询1、2、3的情况比较多,建议为这个字段建立索引。因为索引可以有效的提高检索匹配的效率,尤其是对于数据量比较大的表格。
对于字段值只有2-3种变化的情况,索引可以通过将查找的字段值分类为大部分和少数值来提高查询的效率,因为索引可以有效地缩短查找的时间。如果选择合适的索引类型(如使用数列索引或单列索引),可以将查询时间缩短到非常短的时间,优化SQL的执行效率。
这种情况下为什么效率高
为某个字段设置索引,一方面可以将表数据按照该字段排序,另一方面可以将该字段作为查询条件,快速定位符合条件的数据行。在字段只有几种值的情况下,如果这个字段上没有索引,则需要扫描大量的数据块才能查询出结果。但如果这个字段上建有索引,在使用该字段进行查询时,由于查询的数据量不大,即使进行全表扫描的查询,也可以快速定位到符合条件的记录,而且查询速度与表的大小无关,几乎是常数级别的。
例如,假设有一个表格,表格中包含一列记录学生的分数 score,分数只有0分、50分、60分、70分、80分、90分和100分共7种情况。如果在 score 上建立了索引,那么涉及到 score 的 SQL查询语句,如查询60分分数的学生,将非常快速完成。查询时通过索引,只需要定位到值为60的记录,而不是全表扫描。而没有索引则需要扫描整个表格中所有记录,逐一比较,效率会显著降低。
在这种情况下,如果选择了数列索引(Index for lists of small integers),或使用单列索引(Single-column index),数据库引擎就会将该字段上的索引视为按照该字段值的出现顺序逐行排序,创建出更小的索引空间。这样就可以大大降低表格查询所需的存储资源和检索所需的时间,提高查询效率。
单个字段索引和联合索引是 MySQL 中常见的两种索引类型,它们在索引的实现和使用方面存在较大的差别。
单个字段索引
单个字段索引是针对单个字段构建的索引,它是在表的某列上创建的 B-Tree 索引。使用单列索引查询时,通过比较 B-Tree,查询结果需要寻找索引中的单个值,从而定位到符合条件的行。
单个字段索引的优点是简单易懂,可以用于针对单一字段的高效检索和范围查询。同时,在单个字段上创建索引的代价比较低,索引占用的空间也较小。但是,每个索引只包含了一个字段,因此在多字段条件下无法起到作用,需要建立多个单列索引才能支持多字段查询。
联合索引
联合索引是指在多个(2个或多个)列上建立的索引,可以同列上的单字段索引一样,通过 B-Tree 或哈希算法来实现。而不像多个单列索引那样,每个列都有一个自己的索引结构。
联合索引的优点是可以快速查询多个列,这是单个索引所无法做到的。联合索引可以显著降低索引结构数量,减少占用磁盘空间。而且,在某些情况下,使用联合索引可以比使用单个大索引更为高效,这取决于索引列的特定排列方式。
需要注意的是,联合索引也会带来一定的代价。不仅索引开销大,而且更新数据行时,需要同时更改多个索引。同时,当使用联合索引进行范围查询时,需要完全匹配所需要的前缀才能使用索引。此时,如果索引中包含的前缀长度过大,也会造成额外的索引扫描代价,反而会降低查询效率。
假设有一张用户表格user,包含以下字段:id、name、age、gender和address,那么这里我们以name、age和gender三个字段建立一个联合索引。首先,可以通过以下语句来创建联合索引:
CREATE INDEX idx_name_age_gender ON user (name, age, gender);
以上语句中,idx_name_age_gender
表示索引名称,user
表示表名,(name,age,gender)
表示联合索引的列名,用逗号分隔。
在创建好联合索引后,可以通过以下语句进行 SQL 查询:
SELECT * FROM user WHERE name = '张三' AND age = 20 AND gender = '男';
在上面代码中,通过在WHERE
子句中指定具体的联合索引列和数值来查询,这样就能以最小代价和最优化的方式找到符合条件的记录,因为除了name、age和gender三个值都满足要求之外,查询就无法返回记录了。如果没有定义联合索引,那么这个查询语句将会默认使用单列索引或全表扫描,效率会变得很低。
同时,如果某个查询语句只是针对name、age两个字段或任意其他子集字段查询,联合索引同样可以帮助优化效率。这也体现了联合索引的使用场景比较灵活,能够满足不同查询操作的需求。
联合索引只能在索引的最左列开始进行搜索,如果查询时不使用联合索引的最左列,那么索引就会失效。例如,如果索引是(name, age),则使用语句SELECT * FROM user WHERE age = 20
就不会使用该联合索引。