浅谈mysql的主键和索引

这篇具有很好参考价值的文章主要介绍了浅谈mysql的主键和索引。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在上一篇文章《count(1)、count(*)、count(字段)哪个更靠谱》中,我们提到过主键是优化不了count的查询效率的,需要建索引才可以,那么,是不是意味着主键的效率还不如一般的索引呢?怀着这个疑问,我们一起来了解下mysql主键和索引的相关知识。

mysql数据库的MYISAM和InnoDB引擎所采用的索引的数据存储结构是不一样的,本文所阐述的内容都是基于InnoDB引擎下。

什么是主键

我们引用上一篇文章最后的一段内容:

  • 主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。

  • 主键创建后一定包含一个特殊的唯一性索引,唯一性索引不一定就是主键。

  • 唯一性索引列允许空值, 而主键列不允许为空值。

  • 主键可以被其他表引用为外键,而唯一索引不能。

  • 一个表最多只能创建一个主键,但是可以创建多个唯一索引。

  • 主键更适合那些不容易改变的唯一标识,如自动递增列,身份证号等。

    划重点:

    1、主键是一种约束,从本质上来说并不是索引。

    2、一个表最多只有一个主键。

    3、主键定义后一定会按主键顺序生成一个唯一性的索引,所以一般来说,我们会把主键和主键索引等同看待。

引的类型

关于索引的类型说法有很多,如聚簇索引、非聚簇索引、主键索引、辅助索引、二级索引、次级索引、唯一索引、单列索引、复合索引等等。我们先引用mysql官方的一段话来解释:

  • 在InnoDB,每张表都有一个特殊的索引叫聚簇索引(也叫聚集索引),聚簇索引的B+Tree的叶子节点存的是主键值和整行数据,整张表的数据其实就是存储在聚簇索引中,实际上聚簇索引就是一张按主键顺序存储的表。主键一定是聚簇索引。

  • 除了聚簇索引外的其它索引都叫二级索引,与聚簇索引的区别在于二级索引的叶子节点中只存了索引列和主键值,索引和数据是分开的。非聚簇索引、辅助索引、次级索引都是二次索引的不同说法,唯一索引、单列索引、复合索引都属于二次索引,只是从逻辑角度进行的分类。

  • 通过主键可以直接在聚簇索引找到对应的行数据,通过二级索引需要先找到主键值,再根据主键值到聚簇索引找到对应的行,也就是平常说的要进行一次回表操作,因此,要获取行数据,主键索引效率是最高的(注意:这里强调的是获取到行数据)

  • InnoDB要求每张表都要定义主键,并建议主键采用自增ID的形式,这样可以减少二级索引占用空间,提升索引效率。

    下面是聚簇索引和二级索引的结构:

    浅谈mysql的主键和索引

    浅谈mysql的主键和索引

    通过上面的索引结构可以看出,聚簇索引保存了整张表的数据,所以要获取行数据通过聚簇索引是最快的,但如果只是获取索引列和主键列数据,二次索引结构更小,通过二级索引的效率是最高的。

  • 聚簇索引的建立遵循以下的原则:

    1、如果一个主键被定义了,那么这个主键就是作为聚簇索引。

    2、如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚簇索引。

    3、如果没有主键也没有合适的唯一索引,那么InnoDB内部会生成一个隐藏的主键作为聚簇索引,这个隐藏的主键是一个6个字节的列,该列的值会随着数据的插入自增,但用户不可见且不能用于查询。

那么,我们思考两个问题:

1、主键一定是聚簇索引,聚簇索引是否一定是主键?

2、聚簇索引不是主键,那二级索引叶子节点存放的主键值是什么?

带着这两个问题,我们来做个实验,先建个测试表:

create table test(

 id int not null,

 c1 varchar(10) not null,

 c2 varchar(10) null);

查看索引情况:

select i.* from information_schema.INNODB_SYS_INDEXES i join information_schema.INNODB_SYS_TABLES t on i.table_id=t.table_id where t.name='ecos/test';

浅谈mysql的主键和索引

可以看到,未定义主键的情况下,mysql自动创建了一个隐藏的、用户不可见的主键并作为聚簇索引,符合聚簇索引建立的第3条原则。(在INNODB_SYS_INDEXES系统表中type代表索引的类型,0:一般的索引,1:(GEN_CLUST_INDEX)系统生成的隐藏主键索引,2:唯一索引,3:主键索引)

再创建一个唯一索引:

create unique index unx_c1 on test(c1);

再查看索引情况:

浅谈mysql的主键和索引

可以看到创建的唯一索引自动转变成了主键索引,那么c1是否也转成了主键呢,我们再看表的情况:

浅谈mysql的主键和索引

c1并没有变成primary key,改变的只是索引的类型,这时候从用户视角主键实际上是不存在的。

我们再给表添加主键:

alter table test add PRIMARY key(id);

再看索引和表的主键情况:

浅谈mysql的主键和索引

浅谈mysql的主键和索引

可以看到原来的主键索引已经变成了唯一索引,新加的主键ID成了主键索引。

总结:

1、主键一定是聚簇索引,聚簇索引不一定是主键,但一定是主键索引(我们暂且把系统自动生成的也当主键索引)。

2、二次索引叶子节点存放的主键值准确的说是主键索引值。

3、在mysql的官方文档里面,一直都是以primary key出现的,并且也不支持以create index方式创建,primary key既代表了主键也代表了主键索引,这也造成了我们在理解上的困惑,所以在了解mysql索引结构的时候建议还是把primary key理解为主键索引。

4、在建表的时候就应该定义好主键,并且不再修改,特别是生产环境,主键的修改会影响到所有索引的重建。

5、官方建议主键用自增ID,但在实际业务场景中,应该结合业务实际需要来定义主键,更好的利用主键索引的优势,但要避免用uuid等无序的值。如在订单数据表,订单号本身就按递增规则生成,且具有唯一性,那么用订单号做主键更符合业务需要。

最后回到最开始的问题,count(*)之所以在只有主键的情况下查询效率无法提升,正是由于mysql InnoDB索引结构导致的,count在where条件没有的情况下是要走全表扫描,而主键索引是聚簇索引,包含了整个表的数据,占用空间和分页更多,查询优化器在有二级索引的情况下会优先查找二级索引,二级索引的B+Tree更小,查找效率会更高,覆盖索引优化同样是利用的二级索引的这种优势。

思考:id为主键,下面两个查询返回的结果是一样的吗?

1、select a.* from tbl_order a limit 1;

2、select a.* from tbl_order a where id=(select b.id from tbl_order b limit 1);

浅谈mysql的主键和索引 (qq.com)文章来源地址https://www.toymoban.com/news/detail-481629.html

到了这里,关于浅谈mysql的主键和索引的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【MySQL】更改表的主键报错及解决办法

    报错: [HY000][3750] Unable to create or change a table without a primary key, when the system variable ‘sql_require_primary_key’ is set. Add a primary key to the table or unset this variable to avoid this message. Note that tables without a primary key can cause performance problems in row-based replication, so please consult your DBA before changing

    2024年01月20日
    浏览(43)
  • 浅谈MySQL主键

    常用主键 1)自增 int、bigint等,顺序递增。 2)雪花 雪花算法是因为有时间参数,所以是有序地,而且都是由数字组成。雪花id最大为64位,符合java中long的长度64位,适用于大规模分布式场景。 3)UUID 在一定的范围内唯一的机器生成的标识符,通用唯一标识符 优势: 随机生成

    2024年02月07日
    浏览(34)
  • 主键和外键的含义及区别

    表中经常有一个列或多个列的组合,其值能唯一的标识表中的每一行。这样的一列或多列称为表的主键。 外键:用来表示表与表之间联系,是表中的一个列。 主键和外键都是用于维护数据库完整性的一种机制。 1、主键是唯一标识一条记录,不能重复,不允许为空;而外键可

    2024年02月12日
    浏览(28)
  • Sqlserver查看表的主键,删除主键,修改主键

    1.查看表的结构 EXEC sp_help \\\'表名\\\'; 查询使用 sp_help 存储过程,它将返回有关表的详细信息,包括列名、数据类型、约束等。在结果中查找带有 “PK” 标记的列,它们表示主键约束。 2.查看表的主键信息 EXEC sp_pkeys \\\'表名\\\'; 查询使用 sp_pkeys 存储过程,它将返回指定表的主键信息

    2024年02月07日
    浏览(27)
  • Mysql-InnoDB索引:普通索引、主键索引、唯一索引、组合索引

    事务方面 InnoDB支持事务,MyISAM不支持事务。这是Mysql将默认存储引擎从MyISAM变成InnoDB的重要原因之一 外键方面 InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MyISAM会失败 索引层面 InnoDB是聚集(聚簇)索引,MyISAM是非聚集(非聚簇)索引。 MyISAM 支持 FULLTEXT 类型

    2024年02月03日
    浏览(42)
  • mysql中主键索引和联合索引的原理解析

    主键索引 :按照主键数据从小到大按照从左到右进行排序,叶节点只存储数据区; 接着将上面的页生成出来,页只存储索引和指针,指针指向数据域,当通过主键查找数据时,从B+树的头部开始寻址数据、读取数据。 上面为索引页 下面为数据页 查询select * from table where a=6,

    2024年04月08日
    浏览(29)
  • 【Mysql】复合主键的索引

    复合主键在where中使用查询的时候到底走不走索引呢?例如下表: 当执行以下SQL的时候到底走不走索引呢?             Explain结果: 使用索引   使用索引   使用索引   不使用索引   不使用索引   使用索引   结论:Mysql复合主键的顺序十分重要,WHERE查询条件中会按列匹配

    2023年04月25日
    浏览(70)
  • 【面试】Mysql主键索引普通索引索引和唯一索引的区别是什么?

    在 MySQL 中, 索引是在存储引擎层实现的, 所以并没有统⼀的索引标准, 由于 InnoDB 存储引擎在 MySQL数据库中使⽤最为⼴泛, 下⾯以 InnoDB 为例来分析⼀下其中的索引模型.在 InnoDB 中, 表都是根据主键顺序以索引的形式存放的, InnoDB 使⽤了 B+ 树索引模型,所以数据都是存储在 B+ 树

    2023年04月17日
    浏览(42)
  • Mysql 索引(三)—— 不同索引的创建方式(主键索引、普通索引、唯一键索引)

    了解了主键索引的底层原理,主键索引其实就是 根据主键字段建立相关的数据结构 (B+树),此后在 使用主键字段作为条件查询时,会直接根据主键查找B+树的叶子结点。 除了 主键索引外,普通索引和唯一键索引也是如此,只不过普通索引要稍微绕一点,下面会具体介绍。

    2024年02月03日
    浏览(29)
  • 【后端面经】MySQL主键、唯一索引、联合索引的区别和作用

    目录 0. 简介 1. 主键 2. 唯一索引 3. 联合索引 4. 索引对数据库操作的影响 5. 其他索引 5.1 普通索引 5.2 全文索引 5.3 前缀索引 6. 总结 7. 参考资料 索引是一类特殊的 文件 ,用来存储检索信息,使数据库查找更加快速。 主键是一类特殊的唯一索引,选择某一列元素作为主键,用

    2024年02月09日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包