索引
在MySQL中,查询方式可以根据访问表数据的方式分为两种:全表扫描和使用索引。
-
全表扫描(Full Table Scan):
- 全表扫描是指在查询过程中,MySQL会遍历整个表的每一行来检查满足查询条件的数据。
- 当查询条件无法利用索引或没有适当的索引可用时,MySQL将执行全表扫描。
- 全表扫描可以处理表中的所有行,但在大型表或查询复杂度较高的情况下可能导致较慢的查询速度。
-
使用索引(Index Scan):
- 索引是一种数据结构,用于加速查询操作。MySQL使用B-tree索引来存储和管理数据。
- 当查询条件能够匹配索引列,并且存在适当的索引可用时,MySQL可以使用索引来快速定位满足条件的行。
- 索引扫描可以避免全表扫描,减少查询所需的I/O和处理时间,从而提高查询性能。
在实际情况中,MySQL会根据查询条件、表的大小和索引的使用情况来选择最合适的查询方式。以下是一些关于查询方式的详细点:
-
全表扫描适用于以下情况:
- 查询条件无法利用索引,例如使用不等于(
<>
)操作符、模糊匹配的LIKE操作等。 - 表的规模相对较小,全表扫描的性能仍然可以接受。
- 查询条件无法利用索引,例如使用不等于(
-
使用索引适用于以下情况:
- 查询条件能够匹配索引列,例如使用等于(
=
)操作符、范围查询等。 - 表的规模较大,使用索引可以大幅减少查询时间。
- 查询中涉及到多个列的筛选和排序。
- 查询条件能够匹配索引列,例如使用等于(
请注意以下几点:
- 索引并非总是万能的,有时候错误的索引设计可能导致性能下降。
- 适当的索引设计和维护可以显著提高查询性能,但过多的索引或不必要的索引可能会增加写操作的开销和存储空间占用。
- 索引会随着内容的变化而变化
- 缺点: 创建索引,更新索引 ,需要消耗额外的资源(cpu,磁盘,内存等)
问题
索引是建立在库,还是表上?如果是表上的,建立在表的什么上?
索引是建立在表里的字段上的,也就是索引是根据字段里的内容建立的
哪些字段上适合建立索引?
数据比较大的表,经常查询使用的字段,字段里出现重复率不高的内容
innodb支持的索引
InnoDB是MySQL数据库中一种常用的存储引擎,支持多种类型的索引用于提高查询性能。下面是InnoDB支持的一些常见索引类型的详细介绍:
-
B-tree索引(B树索引):
B-tree索引是InnoDB中最常见的索引类型。它使用B-tree数据结构来组织索引数据。B-tree索引适用于精确匹配和范围查询,能够快速定位数据。B-tree索引支持从左到右的前缀匹配查询,可以用于优化模糊查询。在InnoDB中,主键索引就是一种特殊的B-tree索引。 -
全文索引:
全文索引用于快速搜索文本内容,而不只是单词的匹配。InnoDB支持全文索引,可以对包含文本的列进行全文索引的创建。全文索引能够实现更复杂的文本搜索,例如关键字搜索、词语组合等。在InnoDB中,全文索引使用倒排索引的数据结构来实现。 -
哈希索引:
哈希索引是一种高效的索引类型,适用于等值查询。它使用哈希函数将索引值映射到索引项,因此能够快速定位数据。InnoDB支持哈希索引,但仅适用于内存表(MEMORY表)。哈希索引不支持范围查询和排序操作,因为哈希函数是基于索引值的完整匹配。 -
主键索引:
主键索引是一种特殊的索引类型,用于唯一标识表中的每一行。在InnoDB中,如果表定义了主键(PRIMARY KEY),则主键索引会自动创建。主键索引的值是唯一的,因此可以用于快速查找特定行。主键索引还可以用作外键关系的参考。 -
外键索引:
外键索引是一种用于实现表之间关系的索引类型。它定义了表与表之间的引用关系,确保数据的完整性和一致性。外键索引基于外键关系建立,并指向关联表的主键索引。通过外键索引,可以方便地进行表之间的关联查询和级联操作。
这些索引类型在InnoDB中具有不同的特点和适用场景。根据具体的查询需求和数据特征,选择适合的索引类型可以提高数据库的查询性能和数据操作效率。
innodb结构
hash和b-tree
在InnoDB存储引擎中,支持两种类型的索引:B-tree索引和哈希索引。这些索引具有不同的特点和用途。
B-tree索引:
- B-tree索引是InnoDB默认的索引类型。它使用B-tree数据结构进行组织和存储数据。
- B-tree索引适用于范围查询,例如大于、小于或介于某个值之间的查询。
- B-tree索引可以按照索引字段的顺序存储数据,这使得它对于排序和范围查询非常高效。
- B-tree索引对于插入、更新和删除操作的性能也相对较好。
- B-tree索引可以用作唯一索引或非唯一索引。
哈希索引:
- 哈希索引使用哈希函数将索引键映射到唯一的索引值。它将数据存储为哈希表的形式。
- 哈希索引适用于等值查询,例如通过索引键直接查找某个值。
- 哈希索引对于等值查询非常高效,查询的性能通常非常快。
- 哈希索引不适用于范围查询,因为哈希函数无法保证索引键的顺序。
- 哈希索引不支持部分索引列的查询,只能使用所有索引列进行查询。
- 哈希索引不支持排序操作,因为数据存储在哈希表中,并没有按顺序排列。
优点和缺点:
- B-tree索引的优点包括适用于范围查询、排序和插入、更新、删除操作的高性能。它能够满足更广泛的查询需求,是InnoDB默认的索引类型。
- B-tree索引的缺点是对于等值查询的性能可能不如哈希索引。
- 哈希索引的优点是对于等值查询非常高效,查询速度快。
- 哈希索引的缺点是不支持范围查询、排序和部分索引列的查询,适用性相对较窄。
总的来说,选择使用B-tree索引还是哈希索引取决于具体的查询需求。如果你需要进行范围查询、排序或部分索引列的查询,那么B-tree索引是更好的选择。如果你主要进行等值查询,并且对查询性能有较高的要求,那么哈希索引可能更适合。
索引分类
MySQL 中的索引可以根据不同的特性和用途进行分类。下面是几种常见的索引类型:
-
单列索引(Single Column Index):
单列索引是最基本的索引类型,它仅包含单个列。它可以加快根据该列进行查询、排序和过滤的速度。在创建单列索引时,可以选择普通索引(默认)或唯一索引。- 普通索引(Non-Unique Index):允许索引列中的值重复。
- 唯一索引(Unique Index):要求索引列中的值是唯一的,不能重复。
-
复合索引(Composite Index):
复合索引是包含多个列的索引。它可以根据多个列的组合进行查询、排序和过滤,提高多列条件下的查询性能。复合索引的创建顺序非常重要,因为要遵循最左匹配原则。 -
主键索引(Primary Key Index):
主键索引是一种特殊的唯一索引,用于唯一标识表中的每一行。一个表只能有一个主键索引,并且主键索引通常是自增长的整数列。主键索引对于快速查找和唯一性约束非常有效。 -
外键索引(Foreign Key Index):
外键索引是用于建立表之间关联关系的索引。它通过引用其他表的主键索引,确保数据的完整性和一致性。外键索引可以加速关联查询,并提供了方便的约束功能。 -
全文索引(Full-Text Index):
全文索引用于支持全文搜索,即对文本内容进行关键字搜索。它可以在大文本字段(如文章、评论等)上进行高效的全文搜索操作。 -
哈希索引(Hash Index):
哈希索引使用哈希函数将索引列的值映射到哈希桶中,以提供快速的等值查询。然而,哈希索引只支持精确匹配查询,不支持范围查询或排序操作。此外,哈希索引对于索引列的数据分布要求较高。 -
空间索引(Spatial Index):
空间索引用于对具有空间属性(如地理坐标、几何图形等)的数据进行高效的空间查询,如范围搜索、邻近搜索等。
这些是 MySQL 中常见的索引类型。在设计和选择索引时,需要根据具体的业务需求和查询模式来决定使用哪种类型的索引,以提高查询性能和数据的完整性。
索引创建
在 MySQL 中,可以使用以下方法创建索引:
-
创建表时指定索引:
在创建表时,可以使用CREATE TABLE
语句的INDEX
或KEY
子句来指定索引。下面是一个示例:CREATE TABLE table_name (column1 datatype,column2 datatype,...INDEX index_name (column1, column2, ...) );
在上述示例中,
index_name
是索引的名称,column1, column2, ...
是要包含在索引中的列名。 -
使用
CREATE INDEX
语句创建索引:
可以使用CREATE INDEX
语句在已存在的表上创建索引。下面是一个示例:CREATE INDEX index_name ON table_name (column1, column2, ...);
在上述示例中,
index_name
是索引的名称,table_name
是要创建索引的表名,column1, column2, ...
是要包含在索引中的列名。 -
使用
ALTER TABLE
语句添加索引:
可以使用ALTER TABLE
语句在已存在的表上添加索引。下面是一个示例:ALTER TABLE table_name ADD INDEX index_name (column1, column2, ...);
在上述示例中,
table_name
是要添加索引的表名,index_name
是索引的名称,column1, column2, ...
是要包含在索引中的列名。 -
使用
CREATE UNIQUE INDEX
语句创建唯一索引:
如果需要创建唯一索引,可以使用CREATE UNIQUE INDEX
语句。唯一索引要求索引中的值是唯一的,不能重复。下面是一个示例:CREATE UNIQUE INDEX index_name ON table_name (column1, column2, ...);
在上述示例中,
index_name
是索引的名称,table_name
是要创建索引的表名,column1, column2, ...
是要包含在索引中的列名。
索引的最左匹配原则
索引的最左匹配原则是指,在使用复合索引(Composite Index)时,查询条件从左到右依次匹配索引的左侧列,并且只有在前面的列都匹配成功的情况下,才会继续匹配后面的列。
具体来说,如果有一个复合索引 (column1, column2, column3)
,则最左匹配原则要求查询条件中至少包含索引的最左侧列 column1
,然后才能匹配第二列 column2
,最后才能匹配第三列 column3
。
最左匹配原则的重要性在于索引的有效性。当查询条件中只涉及到索引的左侧列时,数据库可以直接使用索引进行快速定位和过滤,大大提高查询效率。而如果查询条件不满足最左匹配原则,索引的效果将会大打折扣,数据库可能需要遍历更多的数据行才能找到匹配的结果,导致查询性能下降。
以下是几个示例来说明最左匹配原则:
-
考虑一个复合索引
(column1, column2, column3)
,查询条件为WHERE column1 = 'A'
。根据最左匹配原则,只使用了索引的最左侧列column1
,这时索引可以被有效利用。 -
考虑同样的复合索引
(column1, column2, column3)
,查询条件为WHERE column2 = 'B'
。根据最左匹配原则,索引的最左侧列column1
并未出现在查询条件中,因此索引将无法使用,查询性能可能较差。 -
考虑同样的复合索引
(column1, column2, column3)
,查询条件为WHERE column1 = 'A' AND column2 = 'B'
。根据最左匹配原则,查询条件包含了索引的最左侧两列,因此索引可以被充分利用。
注意如:
-
复合索引
(column1, column2, column3)
,查询条件为WHERE column2 = 'A' AND column1 = 'B'
。查询条件和复合索引顺序不一样,用不到复合索引了。 -
如果单一索引和复合索引都能进行搜索,这样mysql会选择单一索引,因为复合索引需要更多的存储空间。
如何查看索引
在 MySQL 中,可以使用以下方法来查看表的索引:
-
使用
SHOW INDEX
语句:
可以使用SHOW INDEX
语句来查看表的索引信息。下面是使用该语句的示例:SHOW INDEX FROM table_name;
在上述示例中,
table_name
是要查看索引的表名。执行该语句后,将返回表的索引信息,包括索引名称、关联的列、索引类型、唯一性等信息。 -
使用
SHOW CREATE TABLE
语句:
可以使用SHOW CREATE TABLE
语句来查看表的创建语句,其中包含了索引的定义。下面是使用该语句的示例:SHOW CREATE TABLE table_name;
在上述示例中,
table_name
是要查看索引的表名。执行该语句后,将返回包含表的创建语句的结果,其中包括了索引的定义信息。 -
使用
INFORMATION_SCHEMA
数据库:
MySQL 提供了INFORMATION_SCHEMA
数据库,其中包含了关于数据库、表、索引等的元数据信息。可以查询INFORMATION_SCHEMA
数据库的相关表来获取索引信息。下面是一个示例查询:SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema = 'your_database' AND table_name = 'your_table';
在上述示例中,将
your_database
替换为实际的数据库名,your_table
替换为实际的表名。执行该查询后,将返回与指定表相关的索引信息。
基数(Cardinality)
在MySQL中,基数(Cardinality)是指数据库表中某个列的唯一值的数量。它是衡量列的数据分布和选择性的指标。基数的高低可以影响查询性能和索引的效果。
基数的值越高,表示该列中的唯一值越多,数据分布更均匀,选择性更好。相反,基数较低表示该列中的唯一值较少,数据分布不均匀,选择性较差。
对于MySQL来说,基数是由存储引擎统计计算得出的,并保存在索引的统计信息中。存储引擎会根据实际数据和更新操作的频率来更新基数的值。
基数对于查询优化和索引的选择非常重要。当一个查询涉及到某个列时,优化器会利用基数信息来判断是否使用索引以及选择最优的执行计划。如果基数较低,使用索引可能并不高效,而全表扫描可能更合适。
在创建索引时,基数也是一个重要的考虑因素。如果某个列的基数非常高,那么该列的索引可能会非常有用,因为它可以帮助快速过滤掉大量的数据。相反,如果基数较低,索引的效果可能较差,因为它可能需要扫描更多的索引页来获取需要的数据。
可以通过使用SHOW INDEX
命令或查询information_schema.statistics
系统表来查看表中索引的基数信息。例如,使用以下命令查看表mytable
的索引信息:
SHOW INDEX FROM mytable;
在输出结果中,可以看到每个索引的Cardinality
列显示了索引的基数值。
需要注意的是,基数并不是唯一衡量索引性能的指标,其他因素如数据分布、查询模式等也会影响索引的选择和效果。因此,在设计和优化数据库时,综合考虑基数以及其他相关因素是很重要的。