面试题:MySQL为什么一定要有一个主键

什么是主键?

  • 唯一标识一行记录
  • msql:innodb:mysql会根据主键创建主键索引
  • 主键可以一个列,也可以联合主键
  • 主键的选择要:不重复、唯一、没有空值,长度固定、自增
  • MySQL中只要有主键会立刻根据主键创建主键索引表(B+树),叶子结点存储数据和索引,非叶子节点存储索引
  • 自增主键插入比较快,不会涉及到叶子结点分裂问题。

为什么一定要有主键?

        有主键查询速度会更快。如果没有主键,那么这些表就会依赖一个全局序列计数器生成的ROW_ID来构造一个隐式的聚簇索引,就会导致竞争引起性能问题。
没有主键,更新或删除表中特定行会很困难。

延申

聚簇索引和非聚簇索引

  1. 很简单记住一句话:找到了索引就找到了需要的数据,那么这个索引就是聚簇索引,所以主键就是聚簇索引,修改聚簇索引其实就是修改主键。(索引就是我们要找的数据
  2. 索引的存储和数据的存储是分离的,也就是说找到了索引但没找到数据,需要根据索引上的值(主键)再次回表查询,非聚簇索引也叫做辅助索引。(找到了索引还要根据索引查询数据

索引覆盖,索引下推,回表 

索引覆盖

索引覆盖是指查询操作可以完全通过索引来完成,而无需访问表中的数据行。当一个查询的所有数据需求都可以通过索引中的数据来满足时,就发生了索引覆盖。这样,数据库就不需要进行额外的数据查找,从而减少了磁盘I/O操作,提高了查询性能1

例如,如果有一个查询语句是:

SELECT name, age FROM users WHERE name = '张三';

如果nameage都包含在一个索引中,那么这个查询就可以通过索引覆盖来完成,不需要回表查询。

索引下推

索引下推是MySQL 5.6及以上版本引入的优化技术。它允许在索引遍历过程中应用查询条件,从而减少访问不必要数据的次数。这意味着数据库引擎会在索引层面过滤数据,而不是在找到所有可能的索引后再在服务器层面进行过滤2

例如,对于查询:

SELECT * FROM users WHERE name LIKE '张%' AND age = 30;

在启用索引下推的情况下,数据库引擎会在遍历索引时直接应用age = 30的条件,而不是在找到所有姓张的记录后再进行过滤。

重要考虑事项

  • 索引覆盖的一个关键要求是查询中的所有列都必须在索引中。如果查询引用了索引中没有的列,那么就无法实现索引覆盖。

  • 索引下推可以显著减少因为回表操作而导致的性能开销。它通过在存储引擎层面进行更多的数据过滤,减少了服务器层面的工作量。

  • 在设计索引时,应该考虑查询模式,以便最大限度地利用索引覆盖和索引下推的优势。

回表

回表查询是数据库操作中的一个术语,特别是在使用索引进行数据检索时。它发生在使用非聚集索引(Secondary Index)进行查询时,索引中只包含了索引列的副本以及指向对应主键的引用。当查询语句中需要返回的列不在索引列上时,即使通过索引定位了相关行,仍然需要回表获取其他列的值。这意味着数据库需要进行两次查找:一次在非聚集索引上定位数据,一次在聚集索引或主键索引上获取完整的数据行。

代码示例

在MySQL中,如果有一个表,其中id是主键,而name有一个普通索引。当执行如下查询时:

SELECT * FROM table WHERE name = 'ls';

由于name列有一个普通索引,查询会首先使用这个索引。但是,普通索引只存储了name值和对应的主键id,并没有sextype等其他信息。因此,数据库需要回到主键索引上,根据id再次查询以获取完整的数据行。

优化方法

为了避免回表查询,可以使用索引覆盖。这意味着查询涉及的所有列都包含在索引中,从而避免了第二次查询。例如,如果查询只涉及idname

SELECT id, name FROM table WHERE name = 'ls';

这样就不会发生回表查询。但如果查询包括sex列:

SELECT id, name, sex FROM table WHERE name = 'ls';

就需要回表查询,因为sex不在name索引中。解决这个问题的方法是创建一个包含namesex的联合索引。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涵冰...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值