阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?

本文 的 原文 地址

本文 的 原文 地址

尼恩说在前面:

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、shein 希音、shopee、百度、网易的面试资格,遇到很多很重要的面试题:

  • mysql中,一个表最多只能加多少个索引嘛?一个联合索引最多只能多少列呢?
  • 索引加多了,会存在哪些问题呢?

  • InnoDB存储引擎

  • MyISAM存储引擎

  • 一个表设计多少个索引合理呢?

  • 索引设计过多存在哪些问题?

  • 阿里巴巴编程规范中, 单表索引数量,建议控制在5个以内 ,为什么?

前几天 小伙伴面试阿里,遇到了这个问题。但是由于 没有回答好,导致面试挂了。

小伙伴面试完了之后,来求助尼恩。那么,遇到 这个问题,该如何才能回答得很漂亮,才能 让面试官刮目相看、口水直流。

所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。

当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典》V145版本PDF集群,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,后台回复:领电子书

1. 索引基础 :一个 表的 "数据目录"

1.1 什么是 索引?

  • 没有索引:数据库要扫描整张表,就像你从图书馆第一本书开始找
  • 有索引:直接定位到数据位置,效率提升几十甚至上百倍

索引就是"数据的目录" , 想象一下你去图书馆找书,没有目录的话你得一本本翻,有了目录就能直接找到想要的书。

索引就是数据库的"数据目录",它能帮你快速定位数据。

在MySQL中,索引 是一种特殊的数据结构,通常是B+树,它存储着字段值 和对应记录的主键值。

1.2 为什么需要索引?

没有索引时,数据库要执行全表扫描,就像你从图书馆第一本书开始一本本找,数据量越大查询越慢。

有索引后,数据库可以直接定位数据位置,效率提升几十甚至上百倍。

数据量越大, 索引的价值就大, 在百万级、甚至千万级的 表中,有索引的查询可能只需几毫秒,没索引可能要几秒, 甚至更久。

但凡事都有不利的一面, 索引不是万能的,它是以额外存储空间和写入性能为代价换取查询速度的提升,需要权衡利弊。

1.2 索引的常见类型

索引的常见类型 有:

  • 普通索引:最基本的索引,没有任何限制
  • 唯一索引:要求索引列的值必须唯一
  • 主键索引:特殊的唯一索引,不允许有空值
  • 联合索引:多个列组合的索引

普通索引是最基本的索引类型,没有任何限制,允许重复值和空值。

唯一索引要求索引列的值必须唯一,但允许有空值。

主键索引是特殊的唯一索引,不允许有空值,每个表只能有一个。

联合索引是多个列组合的索引,遵循最左前缀原则。

此外还有全文索引、空间索引等特殊类型。

不同类型的索引适用于不同场景,比如用户名适合用唯一索引,文章内容适合用全文索引。

2. InnoDB存储引擎 的 索引 限制

InnoDB存储引擎 是 MySQL 最常用的存储引擎,

InnoDB 作为MySQL5.5后的默认引擎,InnoDB支持事务、行级锁、外键约束等高级功能。

InnoDB 的索引采用聚簇索引(主键索引) + 非聚簇索引 (二级索引) 结合的结构,主键索引的叶子节点直接存储行数据,这使得主键查询特别高效。

InnoDB还支持MVCC多版本并发控制,大大提高了并发读写性能。

对于大多数业务场景,InnoDB都是最佳选择。

InnoDB是MySQL最常用的存储引擎,它就像一辆高性能跑车,既稳定又快速。

InnoDB存储引擎 索引数量限制

  • 最多64个普通索引 + 1个主键索引 = 65个
  • 每个索引最多包含16个字段

尼恩对索引 使用建议:

  • 虽然能创建 65个,除非迫不得已,不建议这么干!

  • 就比如说,像一个人能吃10碗饭,不代表就一定要吃10碗。

2.1 InnoDB 索引 的 数量限制

根据MySQL官方文档, InnoDB存储引擎 它最多允许 一个表最多 64个二级索引(即非主键索引),

官方文档有说明 如下

image.png

链接如下:

dev.mysql.com/doc/refman/…

InnoDB最多允许64个二级索引(非主键索引), 当然, 还有 加上1个主键索引,总共65个索引。

那在InnoDB中,一个表,最多可以有 64+1=65 个索引

而对于一个索引,最多有多少列呢?

2.2 InnoDB 索引列 的 数量限制

InnoDB 中,一个 索引 最多 能允许 多少个 列 ?

结论是: 一个 索引 最多是16列。

官方文档也是有说明的:

image.png

链接如下:

dev.mysql.com/doc/refman/…

每个索引最多可以包含16个字段,这意味, 可以创建一个包含16个字段的超级联合索引。

但要注意,这些是理论最大值,实际应用中应该远低于这个限制。

索引越多,或者一个索引里边的 列越多, 维护成本越高,特别是对于写入频繁的表,过多的索引会严重影响性能。

通常建议单表索引不超过5-8个,核心查询字段优先建索引。

对于联合索引,字段数最好控制在3-5个以内。

尼恩 建议是 : 定期使用EXPLAIN分析查询语句,确保索引被正确使用,删除冗余和低效的索引。

3. MyISAM存储引擎 的 索引 限制

MyISAM 是 MySQL早期的默认存储引擎,虽然现在用得少了,但在某些场景下仍有价值。

MyISAM 适合读多写少的场景。

MyISAM 不支持事务和行级锁,但查询速度非常快,特别适合读多写少的场景。

尼恩提示:MyISAM的表级锁在写入时会锁定整个表,不适合高并发写入场景。

3.1 索引数量限制

MyISAM每个表最多支持64个索引,主键索引不计入此限制。

每个索引最多可以包含16个字段,与InnoDB相同。

MyISAM的索引使用B-tree结构存储,支持前缀索引,可以只对字段的前N个字符建立索引。

MyISAM存储引擎 的 索引 限制 如下:

  • 最多64个索引(主键不算在内)
  • 每个索引最多16个字段

3.2 MyISAM 与InnoDB的区别

MyISAM和InnoDB的主要区别包括:

  • MyISAM 不支持事务
  • MyISAM 表级锁(不是行级锁)
  • MyISAM 适合读多写少的场景

MyISAM不支持事务,而InnoDB支持;

MyISAM只有表级锁,InnoDB支持行级锁;

MyISAM不支持外键,InnoDB支持;

MyISAM的崩溃恢复能力较弱,InnoDB更可靠;

MyISAM的全文索引较早出现,但现在InnoDB也支持了。

选择存储引擎时,如果不需要事务且读多写少,可以考虑MyISAM,否则应该选择InnoDB。

4. 索引数量:少即是多

在数据库设计中,索引数量应该遵循"少即是多"的原则。

过多的索引不仅不能提高性能,反而会带来各种问题。

索引就像书中的目录,一本几百页的书有3-5个目录章节就足够了,如果每页都做一个目录,反而会让查找变得困难。

数据库索引也是如此,需要精心设计,只给真正需要的查询条件建立索引。

4.1 阿里巴巴规范建议

日常开发中,一个表设计多少个索引合适呢?

阿里巴巴《Java开发手册》技术文档,单表索引数量建议控制在5个以内, 单个索引的字段数不超过5个

阿里巴巴《Java开发手册》建议单表索引数量控制在5个以内,这是基于多年实战经验得出的结论。

5个索引对于大多数业务场景已经足够,能够覆盖主要的查询需求。

这个建议不是绝对的,对于特别复杂的业务表可以适当增加,但必须有充分的理由。

规范还建议单个索引的字段数不超过5个,避免创建过于复杂的联合索引。

总之: 适当的索引能提高查询效率,过多的索引会影响数据库表的插入和更新功能。

有些时候,不加索引更合适:

  • 数据量少的表,不适合加索引
  • 更新比较频繁的也不适合加索引

4.2 为什么 阿里巴巴规范建议 是5个?

阿里巴巴的《Java开发手册》建议单表索引不超过5个,为啥呢?

因为,索引 太多的 "副作用" :

  • 写数据变慢‌:就像你每写一篇日记,都要在10个不同的目录里更新位置,累不累?

  • 占用空间大‌:每个索引都要单独存一份数据,就像你为了找书方便,买了10本一模一样的字典放家里

  • MySQL会犯选择困难症‌:索引太多,MySQL反而可能选错最快的查询路径

  • 维护成本高‌:备份、迁移数据时,索引越多越慢

所以,现实中的最佳实践: 5个以内最健康。

5. 索引过多会 导致的 "七宗罪"

索引虽然能提高查询速度,但过多索引会带来一系列问题,过度索引带来的性能下降和维护困难 , 这里 总结为索引的"七宗罪"。

理解 "七宗罪" 问题,有助于我们更好地设计索引策略,避免过度索引带来的性能下降和维护困难。

5.1 第一宗罪:写入变慢

每次执行INSERT、UPDATE、DELETE操作时,MySQL不仅要修改数据,还要更新所有相关的索引。

索引越多,写入操作就越慢。

特别是在批量导入数据时,索引会显著降低导入速度。

测试表明,一个没有索引的表可能比有10个索引的表写入速度快10倍以上。

对于在线web服务系统(如电商平台、 金融交易平台),过多的索引会导致系统吞吐量大幅下降。

5.2 第二宗罪:磁盘 空间浪费

占用空间大‌:每个索引都要单独存一份数据,就像你为了找书方便,买了10本一模一样的字典放家里

每个索引都需要额外的 磁盘 存储空间。

对于InnoDB,索引和数据存储在同一个文件中,索引越多,文件越大。

一个包含10个索引的百万级数据表,索引可能占用几GB甚至更多的空间。

这不仅增加了存储成本,还会影响备份恢复的速度。

5.3 第三宗罪:缓存效率降低

InnoDB使用 Buffer Pool 缓冲池来缓存数据和索引。

索引太多会占用大量 Buffer Pool 缓冲池空间,导致数据和索引的缓存命中率下降。

当 Buffer Pool 缓冲池无法容纳常用数据时,MySQL就需要频繁地从磁盘读取数据,严重影响性能。

合理的索引数量可以让缓冲池缓存更多热点数据。

5.4 第4宗罪:锁竞争加剧

在高并发环境下,索引更新会导致锁竞争加剧。

特别是当多个事务同时修改同一索引时,可能出现锁等待甚至死锁。

InnoDB的行级锁虽然缓解了这个问题,但索引太多仍然会增加锁冲突的概率,影响系统并发性能。

5.5 第5宗罪:优化器困惑

MySQL会犯选择困难症‌:索引太多,MySQL反而可能选错最快的查询路径

当表中有多个索引时,MySQL优化器需要选择使用哪个索引来执行查询。

索引太多会增加优化器做出错误选择的风险,可能导致性能反而下降。

比如优化器可能选择区分度不高的索引,或者错误估计索引的选择性。这时就需要使用FORCE INDEX等提示来强制使用特定索引。

5.6 第6宗罪:维护困难

索引越多,数据库维护工作就越复杂。

ALTER TABLE操作会变得更慢,特别是在大表上添加或删除索引可能需要很长时间。

备份恢复也会变慢,因为需要处理更多的索引数据。

此外,监控和管理大量索引也需要更多的时间和精力。

5.7 第7宗罪:统计信息更新变慢

MySQL使用统计信息来优化查询执行计划。

索引越多,收集和维护统计信息所需的时间和资源就越多。

在数据变化频繁的表上,过时的统计信息可能导致优化器选择低效的执行计划。

虽然可以手动分析表来更新统计信息,但这会增加维护负担。

6. 索引使用实战技巧

掌握了索引的基本原理后,尼恩建议大家 需要了解一些索引的实战技巧, 帮助我们在实际项目中更好地设计和使用索引。

大家对于 索引的使用,存在很多误区,其中 最大的误区是认为"索引越多查询越快",实际上索引过多会降低整体性能。

另一个误区是为所有查询字段都建索引,这会导致索引泛滥。还有人认为联合索引字段顺序无关紧要,实际上顺序对索引效率影响很大。

此外,过度依赖自动创建的索引、不评估索引使用效果、不删除无用索引等都是常见问题。

6.1 哪些情况不加索引?

第一:数据量小的表(如配置表)不需要索引。为啥呢 ? 因为数据量小的表 在查询的时候, 全表扫描可能比索引查找更快。

第二:频繁更新的字段(写多读少的字段),要谨慎加索引。为啥呢 ? 因为每次更新都需要维护索引。

第三:区分度低的字段(如性别、状态标志),通常不适合单独建索引。为啥呢 ?因为索引效果不明显。

第四:太长的字段(如TEXT)不要加索引。如果一定要加,就要使用前缀索引。

第五: NULL值过多的字段,也不建议 加索引。

6.2 如何设计高效索引?

  • 首先分析业务查询模式,优先为高频查询条件建索引。

  • 联合索引要注意字段顺序,区分度高的字段放前面。

  • 避免创建冗余索引,比如已有(a,b)索引就不需要单独建a索引。

  • 定期使用EXPLAIN分析慢查询,优化索引策略。

  • 考虑使用覆盖索引减少回表操作。

  • 对于长字符串,考虑使用前缀索引节省空间。

6.3 对 索引进行 定期监控和优化

索引不是建完就一劳永逸的,需要定期监控和优化。

建议每月至少检查一次索引使用情况,删除无用索引。

使用SHOW INDEX FROM table命令可以查看表的索引信息,包括索引名称、字段、基数等。

通过sys.schema_unused_indexes 视图可以找出长期未使用的索引。

EXPLAIN命令可以分析查询是否使用了合适的索引。

对于数据变化大的表,定期ANALYZE TABLE更新统计信息。

监控索引碎片化程度,必要时重建索引。

建立索引变更评审机制,避免随意添加索引。记录索引变更历史,便于问题追踪。

对于重要系统,可以考虑使用索引管理工具。

7. 索引的 真实案例分享

理论结合实践才能更好掌握索引设计,下面分享两个真实案例。

这些案例来自实际项目经验,展示了如何根据具体业务需求设计合理的索引策略,以及不当索引设计可能导致的问题和解决方案。

案例1:电商系统用户表 的索引案例分享

主键使用自增user_id,保证写入性能。

mobile和email字段建立唯一索引,用于登录和密码找回。

register_time建立索引用于新用户分析。

last_login建立索引用于活跃用户统计。

nickname使用前缀索引支持模糊搜索。

避免为gender等低区分度字段单独建索引。

定期清理不活跃用户的索引条目。

案例2:订单系统 订单表 的索引案例分享

主键使用order_id,分布式系统可以考虑雪花ID。

user_id建立索引支持用户查询。

create_time建立索引支持时间范围查询。

status和payment_type建立联合索引用于订单分析。

避免为price等频繁更新的字段单独建索引。

考虑使用部分索引只索引未完成订单。定期归档历史订单减少索引大小。

8. 总结:索引使用黄金法则

经过前面的详细讲解,我们可以总结出一些索引使用的黄金法则。‘

记住这些法则可以帮助我们避免常见的索引设计错误,建立高效的数据库结构。

  • 不是所有字段都需要索引,只为真正需要的查询条件建索引。

  • 联合索引优于多个单列索引,但要注意字段顺序。

  • 区分度高的字段更适合索引,低区分度字段考虑联合索引。

  • 定期维护比盲目添加更重要,及时删除无用索引。

  • 5个以内最健康,超过8个要三思,必须有充分理由。

  • 理解业务查询模式是设计好索引的前提。

  • 监控和优化是持续过程,不是一次性的工作。

这些法则不是死板的教条,而是指导性的原则,在实际应用中需要根据具体情况进行调整。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
2月前
|
机器学习/深度学习 关系型数据库 MySQL
对比MySQL全文索引与常规索引的互异性
现在,你或许明白了这两种索引的差异,但任何技术决策都不应仅仅基于理论之上。你可以创建你的数据库实验环境,尝试不同类型的索引,看看它们如何影响性能,感受它们真实的力量。只有这样,你才能熟悉它们,掌握什么时候使用全文索引,什么时候使用常规索引,以适应复杂多变的业务需求。
69 12
|
1月前
|
SQL Java 数据库连接
阿里腾讯互联网公司校招 Java 面试题总结及答案解析
本文总结了阿里巴巴和腾讯等互联网大厂的Java校招面试题及答案,涵盖Java基础、多线程、集合框架、数据库、Spring与MyBatis框架等内容。从数据类型、面向对象特性到异常处理,从线程安全到SQL优化,再到IOC原理与MyBatis结果封装,全面梳理常见考点。通过详细解析,帮助求职者系统掌握Java核心知识,为校招做好充分准备。资源链接:[点击下载](https://pan.quark.cn/s/14fcf913bae6)。
45 2
|
2月前
|
SQL 存储 关系型数据库
滴滴面试:明明 mysql 加的是 行锁,怎么就变 表锁 了?
滴滴面试:明明 mysql 加的是 行锁,怎么就变 表锁 了?
|
17天前
|
人工智能 运维 关系型数据库
数据库运维:mysql 数据库迁移方法-mysqldump
本文介绍了MySQL数据库迁移的方法与技巧,重点探讨了数据量大小对迁移方式的影响。对于10GB以下的小型数据库,推荐使用mysqldump进行逻辑导出和source导入;10GB以上可考虑mydumper与myloader工具;100GB以上则建议物理迁移。文中还提供了统计数据库及表空间大小的SQL语句,并讲解了如何使用mysqldump导出存储过程、函数和数据结构。通过结合实际应用场景选择合适的工具与方法,可实现高效的数据迁移。
115 1
|
2月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
4月前
|
关系型数据库 MySQL Java
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
|
2月前
|
存储 关系型数据库 MySQL
大数据新视界 --面向数据分析师的大数据大厂之 MySQL 基础秘籍:轻松创建数据库与表,踏入大数据殿堂
本文详细介绍了在 MySQL 中创建数据库和表的方法。包括安装 MySQL、用命令行和图形化工具创建数据库、选择数据库、创建表(含数据类型介绍与选择建议、案例分析、最佳实践与注意事项)以及查看数据库和表的内容。文章专业、严谨且具可操作性,对数据管理有实际帮助。
大数据新视界 --面向数据分析师的大数据大厂之 MySQL 基础秘籍:轻松创建数据库与表,踏入大数据殿堂
|
2月前
|
SQL 关系型数据库 MySQL
MySQL下载安装全攻略!小白也能轻松上手,从此数据库不再难搞!
这是一份详细的MySQL安装与配置教程,适合初学者快速上手。内容涵盖从下载到安装的每一步操作,包括选择版本、设置路径、配置端口及密码等。同时提供基础操作指南,如数据库管理、数据表增删改查、用户权限设置等。还介绍了备份恢复、图形化工具使用和性能优化技巧,帮助用户全面掌握MySQL的使用方法。附带常见问题解决方法,保姆级教学让你无忧入门!
MySQL下载安装全攻略!小白也能轻松上手,从此数据库不再难搞!
|
4月前
|
关系型数据库 MySQL 数据库连接
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
636 82

推荐镜像

更多