ToB企服应用市场:ToB评测及商务社交产业平台

标题: MySQL 索引 详解(保姆级教程) [打印本页]

作者: 王柳    时间: 2024-9-5 17:28
标题: MySQL 索引 详解(保姆级教程)
一、索引概述


索引是帮助 MySQL 高效获取数据数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查询算法,这种数据结构就是索引。

二、索引的优缺点


优点:

缺点:


三、索引结构

3.1  索引结构介绍


索引结构描述B+Tree最常见的索引范例,大部分引擎都支持B+树索引(默认)Hash底层数据结构是用哈希表实现,只有精确匹配索引列的查询才有效,不支持范围查询R-Tree(空间索引)空间索引是 MyISAM 引擎的一个特殊索引范例,重要用于地理空间数据范例(通常使用较少)Full-Text(全文索引)是一种通过创建倒排索引,快速匹配文档的方式,雷同于 Lucene, Solr, ES(通常使用较少)  3.2  差别存储引擎对索引支持情况


索引InnoDBMyISAMMemoryB+Tree索引支持支持支持Hash索引不支持不支持支持R-Tree索引不支持支持不支持Full-text5.6版本后支持支持不支持  我们寻常所说的索引,假如没有特殊指明,都是指B+树结构组织的索引。

 四、数据结构介绍(二叉树、红黑树、Btree、B+tree)

4.1  二叉树

二叉树(Binary Tree)是一种特殊的树状数据结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的定义如下:
一个二叉树可以为空(即没有节点),或者由一个根节点和两颗分别称为左子树和右子树的二叉树组成。
二叉树的特点:

 4.2  红黑树

红黑树(Red-Black Tree)是一种自平衡的二叉查找树,它在插入和删除操作后通过重新安排节点的颜色来保持平衡。红黑树的名称来源于每个节点上的颜色标记,每个节点可以是红色或玄色。
红黑树具有以下特点:
这些特点确保了红黑树的关键性质,即从根节点到任何叶子节点的最长路径不会超过最短路径的两倍,从而保持了树的平衡性。这种平衡性使得红黑树在实际应用中非常高效,常被用作聚集、映射等数据结构的底子。

 红黑树缺点:大数据量情况下,层级较深,检索速度慢的题目。

4.3  B-Tree(多路平衡查找树)

B-Tree(B树)是一种用于存储和组织大量数据的自平衡搜索树结构。它被广泛应用于数据库和文件系统等领域,以提供高效的数据访问和查询性能。
B-Tree的特点包罗:
B-Tree的基本操作包罗插入、删除和查找。在插入和删除操作时,B-Tree会通过重新分配关键字和调整节点来保持平衡。通过使用B-Tree索引,可以显著提高数据的检索效率,尤其是对于大规模的数据集。
须要留意的是,B-Tree并不仅限于二叉树的结构,每个节点可以包罗多个子节点,使其实用于处理大规模数据集的情况。

 B-Tree 的数据插入过程动画参照:Data Structure Visualization
B-Tree Visualization (假如上面演示链接打不开,请更换)

4.4  B+Tree

B+树(B+Tree)是一种雷同于B-Tree的自平衡搜索树结构,被广泛应用于数据库和文件系统等领域。它是B-Tree的一种变体,相较于B-Tree,在存储和查询性能上有一些优化。
B+树与B-Tree相似,也具有多路平衡性、有序性和磁盘友爱性的特点。但B+树在某些方面具有差别的设计:
B+树通常被用作数据库系统的索引结构,特殊实用于支持范围查询和按顺序访问数据的场景。它的平衡性和磁盘友爱性使得在大规模数据集的存储和检索过程中具有良好的性能表现。
  B+Tree 的数据插入过程动画参照:Data Structure Visualization
B+ Tree Visualization(假如上面演示链接打不开,请更换)

MySQL 索引数据结构对经典的 B+Tree 举行了优化。在原 B+Tree 的底子上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的 B+Tree,提高区间访问的性能。


4.5  Hash 哈希索引

哈希索引(Hash Index)是一种在数据库中用于快速查找数据的索引结构。它通过将关键字(Key)通过散列函数(Hash Function)转换成一个固定长度的散列值(Hash Value),然后将这个散列值与存储位置创建映射关系,从而实现高效的数据查找。
哈希索引的重要特点包罗:
须要留意的是,哈希索引在某些场景下大概结果不如B树索引,因为它无法支持范围查询和排序操作,并且对于存在大量辩论的情况下性能大概会降落。因此,在选择索引范例时须要根据具体的业务需求和数据特点举行综合考虑。

 哈希索引就是接纳肯定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。
假如两个(或多个)键值,映射到一个雷同的槽位上,他们就产生了hash辩论(也称为hash碰撞),可以通过链表来办理。

Hash索引特点:

存储引擎支持:


******面试题******

为什么 InnoDB 存储引擎选择使用 B+Tree 索引结构?


五、索引分类介绍

5.1  索引分类


分类含义特点关键字主键索引针对于表中主键创建的索引默认自动创建,只能有一个PRIMARY唯一索引避免同一个表中某数据列中的值重复可以有多个UNIQUE常规索引快速定位特定数据可以有多个全文索引全文索引查找的是文本中的关键词,而不是比力索引中的值可以有多个FULLTEXT
5.2  InnoDB存储引擎索引分类 

在 InnoDB 存储引擎中,根据索引的存储形式,又可以分为以下两种:

分类含义特点聚集索引(Clustered Index)将数据存储与索引放一块,索引结构的叶子节点生存了行数据必须有,而且只有一个二级索引(Secondary Index)将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键可以存在多个 聚集索引选取规则:

 假设user表的id字段为聚集索引,name字段为二级索引,那么select * from user where name = 'Arm'的查询顺序如下:
会先到二级索引中查询name = Arm的数据,查询到name=Arm的id为10,然后再去聚集索引中查询id=10的数据(聚集索引中存放的是这一行的行数据)流程图如下:


思考题

以下 SQL 语句,哪个执行效率高?为什么?
   select * from user where id = 10;
  select * from user where name = 'Arm';
  -- 备注:id为主键,name字段创建的有索引
  答:第一条语句,因为第二条须要回表查询,相当于两个步骤。 

六、索引的使用(创建、查看、删除)


创建索引:
  CREATE [ UNIQUE | FULLTEXT ] INDEX index_name ON table_name (index_col_name, ...);
表明如下:

例如,假如要在名为users的表上创建一个名为idx_username的普通索引,索引列为username,可以使用以下语句:
        CREATE INDEX idx_username ON users (username);
假如要创建一个唯一索引,可以将关键字UNIQUE添加到语句中:
        CREATE UNIQUE INDEX idx_email ON users (email);
假如要创建一个全文索引,可以将关键字FULLTEXT添加到语句中:
        CREATE FULLTEXT INDEX idx_content ON articles (content);
查看索引:
  SHOW INDEX FROM table_name;
删除索引:
  DROP INDEX index_name ON table_name;
案例: 
   
    
七、SQL性能分析

7.1  SQL执行频率(了解)


 My5QL客户端毗连成功后,通过show [session|global] status命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次。
使用My5QL客户端成功毗连到MySQL服务器后,可以通过使用SHOW SESSION STATUS或SHOW GLOBAL STATUS命令来获取服务器的状态信息。具体地,可以使用以下指令来查看当前数据库中INSERT(插入)、UPDATE(更新)、DELETE(删除)和SELECT(查询)的访问频次:
   SHOW SESSION STATUS LIKE 'Com_insert';
SHOW SESSION STATUS LIKE 'Com_update';
SHOW SESSION STATUS LIKE 'Com_delete';
SHOW SESSION STATUS LIKE 'Com_select';
  在MySQL中,"session"和"global"都是用来指代差别级别的变量或参数。
在命令中,可以使用以下方式来访问差别级别的变量或参数:

须要留意的是,某些变量大概只能在特定级别举行查看或设置。因此,在选择使用"session"还是"global"时,要考虑到所需的变量或参数是否在该级别下可用或具有所需的权限限制。

7.2  慢查询日志(了解)


MySQL慢查询日志是一种记录执行时间超过特定阈值的SQL查询语句的日志。它可以帮助您辨认和优化数据库中的性能瓶颈。
要启用MySQL慢查询日志,您须要执行以下步骤:
1. 打开MySQL设置文件(通常是`my.cnf`或`my.ini`)。您可以在以下位置找到该文件:

2. 在设置文件中找到 `[mysqld]` 部分,假如不存在,则在文件末尾添加该部分。
3. 在 `[mysqld]` 部分中添加以下行来启用慢查询日志并设置阈值(以秒为单位):
   slow_query_log = 1
   slow_query_log_file = /path/to/slow-query.log
   long_query_time = 2

4. 生存并关闭设置文件。
5. 重启MySQL服务,以使设置更改生效。
6. 如今,MySQL慢查询日志已启用。执行时间超过阈值的查询语句将被记录在指定的日志文件中。
要查看慢查询日志,可以使用文本编辑器打开指定的日志文件(`/path/to/slow-query.log`),以查看其中记录的慢查询语句和相关信息。
请留意,启用慢查询日志大概会对数据库性能产生肯定影响,因此在生产环境中应谨慎使用,并根据须要举行适当的设置和管理。

7.3 profile详情(查看SQL执行时间)(了解)


在MySQL中,查询的"profiling"功能可以用于跟踪和分析查询的性能。当启用查询性能分析后,MySQL将记录每个查询的详细执行统计信息。
要启用查询的profiling功能,并查看查询的详细执行统计信息,请按照以下步骤举行操作:
1. 打开MySQL客户端或使用适当的MySQL图形用户界面工具毗连到数据库。
2. 在会话中,执行以下命令以启用查询的profiling功能:
   SET profiling = 1;
3. 然后,执行您希望分析的查询语句。
4. 查询执行完成后,使用以下命令查看查询的profiling详情:
   SHOW PROFILES;
   这将显示一个包罗所有查询的列表,每个查询都有一个唯一的查询ID。
5. 选择要查看其profiling详情的查询,使用以下命令:
   SHOW PROFILE FOR QUERY <query_id>;
   将 `<query_id>` 替换为您要查看的查询的实际查询ID。
   这将显示与所选查询相关的详细执行统计信息,包罗查询的执行时间、扫描行数、临时表创建等等。
6. 查看完查询的profiling详情后,可以使用以下命令来停止profiling并清除已记录的查询信息:
   SET profiling = 0;
请留意,启用查询的profiling大概会对性能产生肯定的影响。因此,应仅在须要详细分析查询性能时才启用profiling,并及时停止profiling以避免不须要的开销。

 7.4  explain执行筹划(重要)


Explain执行筹划是MySQL中的一个命令,用于获取查询语句的执行筹划。执行筹划显示了MySQL优化器在处理查询时选择的操作顺序、使用的索引、数据访问方式等详细信息。


Explain执行筹划的结果集中包罗多个字段,每个字段提供了关于查询执行的差别方面的信息。以下是Explain执行筹划结果集中常见的字段及其含义:
这些字段提供了查询执行的详细信息,可以帮助开发人员了解查询的执行方式、访问模式以及是否存在潜在的性能题目。通过分析Explain执行筹划结果集中的字段,您可以做出相应的优化决策,如创建适当的索引、重写查询或调整查询语句,以提高查询性能。

八、索引使用规则

8.1  最左前缀法则


最左前缀法则是指在使用团结索引举行查询时,必须从索引的最左列开始,并且不能跳过中间的列。假如跳过了某一列,那么索引将只能部分生效,后续字段的索引将会失效。
这个规则的原因是因为团结索引的存储方式是按照索引的多个列依次排序的。当查询时,数据库系统会根据索引的最左列举行查找,并按照索引的顺序逐渐向右查找,直到找到满足所有条件的数据或者无法再继续匹配。
假如我们跳过了某一列举行查询,那么在该列之后的列将无法按照索引的顺序举行查找,导致索引失效。这样就会导致数据库须要扫描更多的数据页来满足查询条件,进而降低查询性能。
因此,在使用团结索引举行查询时,应该遵守最左前缀法则,按照索引列的顺序举行查询,这样可以最大水平地利用索引提供的性能上风。假如须要对多个列举行机动的查询,可以考虑创建更合适的索引或者使用其他查询优化本领来提高性能。

8.2  团结索引避免范围查询 


当使用团结索引举行范围查询(<, >)时,范围查询右侧的列索引将失效。这是因为范围查询须要按照肯定的顺序扫描索引,从而无法完全利用索引的有序性。
为了规避这个索引失效题目,可以考虑改用>=或者<=来取代范围查询。通过使用>=或者<=操作符,可以将范围查询转化为等值查询或者单值查询,从而使得整个团结索引仍然保持有效。
例如,假如要举行范围查询 col1 > 5 AND col2 < 10,可以改写为 col1 >= 5 AND col1 < x AND col2 < 10,其中 x 是大于 5 的一个值。这样,我们将范围查询拆分成两个等值查询,保证了团结索引的有效使用。
须要留意的是,在拆分范围查询时,我们须要根据具体情况选择合适的拆分点(比如上述例子中的 x 值),以保证查询结果的正确性和覆盖率。此外,拆分后的查询条件大概会增加一些逻辑复杂性,须要谨慎设计和测试。

8.3  SQL提示



8.4  覆盖索引


尽量使用覆盖索引(查询使用了索引,并且须要返回的列,在该索引中已经全部能找到),淘汰 select *。
explain 中 extra 字段含义:
using index condition:查找使用了索引,但是须要回表查询数据
using where; using index;:查找使用了索引,但是须要的数据都在索引列中能找到,所以不须要回表查询
假如在聚集索引中直接能找到对应的行,则直接返回行数据,只须要一次查询,哪怕是select *;假如在辅助索引中找聚集索引,如select id, name from xxx where name='xxx';,也只须要通过辅助索引(name)查找到对应的id,返回name和name索引对应的id即可,只须要一次查询;假如是通过辅助索引查找其他字段,则须要回表查询,如select id, name, gender from xxx where name='xxx';
所以尽量不要用select *,轻易出现回表查询,降低效率,除非有团结索引包罗了所有字段
面试题:一张表,有四个字段(id, username, password, status),由于数据量大,须要对以下SQL语句举行优化,该怎样举行才是最优方案:
select id, username, password from tb_user where username='itcast';
解:给username和password字段创建团结索引,则不须要回表查询,直接覆盖索引

8.5  前缀索引


当字段范例为字符串(varchar, text等)时,有时间须要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率,此时可以只降字符串的一部分前缀,创建索引,这样可以大大节约索引空间,从而提高索引效率。
语法:create index idx_xxxx on table_name(columnn(n));
前缀长度:可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
求选择性公式:

8.6 单列索引与团结索引


单列索引:即一个索引只包罗单个列
团结索引:即一个索引包罗了多个列
在业务场景中,假如存在多个查询条件,考虑针对于查询字段创建索引时,建议创建团结索引,而非单列索引。
单列索引情况:
explain select id, phone, name from tb_user where phone = '17799990010' and name = '韩信';
这句只会用到phone索引字段
留意事项



九、索引设计原则


设计原则


十、索引失效情况

10.1  索引列运算


 在索引列上举行运算操作,索引将失效。如:explain select * from tb_user where substring(phone, 10, 2) = '15';
索引列运算是指在查询条件或者索引创建时对索引列举行运算(如计算、函数操作等)。在某些情况下,索引列的运算大概导致索引失效。以下是一些常见的原因:
为了避免索引失效的题目,应该尽量避免在查询条件或者索引创建时对索引列举行运算。假如确实须要使用运算,可以考虑以下办理方案:


10.2  字符串不加引号



假如在查询条件或创建索引时字符串没有加上引号,大概会导致索引失效。以下是一些常见的原因:
为了避免索引失效的题目,应确保在查询条件和创建索引时,所有的字符串值都要正确地用引号括起来。这样可以使数据库正确辨认字符串范例,并按照字符串的排序规则举行比力和索引优化。同时,建议参考相关数据库的文档以了解具体的语法规则和最佳实践。

10.3  模糊查询


模糊查询中,假如仅仅是尾部模糊匹配,索引不会是失效;假如是头部模糊匹配,索引失效。如:explain select * from tb_user where profession like '%工程';,前后都有 % 也会失效。
以下是关于尾部模糊匹配和头部模糊匹配对索引失效的原因:
重要原因在于,索引是按照肯定的顺序存储数据的,而模糊匹配的头部通配符使得须要遍历整个索引举行匹配,无法通过索引的有序性举行高效的定位和筛选。

10.4  or毗连的条件


当使用OR操作符将多个条件组合在一起时,假如其中一个条件的列没有索引,那么涉及的索引不会被用到。这是由于以下原因:
为了办理这个题目,可以考虑以下方案:


10.5  数据分布影响


当MySQL评估使用索引比全表扫描更慢时,会选择不使用索引。以下是一个例子:
对于一个学生表,假如包罗列info,并且大部分记录的info字段为空,并且该列设置了索引,当执行以下查询时:
SELECT * FROM student WHERE info IS NULL;
在这种情况下,MySQL的优化器大概会选择不使用该列的索引。
原因如下:
基于以上原因,MySQL优化器大概会选择不使用该列的索引,而是通过全表扫描来查找info为空的记录。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4