MySQL 可以对相同字段创建不同索引?
Oracle 不允许同一个字段存在两个相同索引,但这个和 MySQL 的设计不太相同,通过实验,了解一下 MySQL 这种场景的情况。
作者:刘晨,网名 bisal ,具有十年以上的应用运维工作经验,目前主要从事数据库应用研发能力提升和技术管理相关的工作,Oracle ACE(Alumni),腾讯云TVP,拥有 Oracle OCM & OCP 、EXIN DevOps Master 、SCJP 等国际认证,国内首批 Oracle YEP 成员,OCMU 成员,《DevOps 最佳实践》中文译者之一,CSDN & ITPub 专家博主,公众号”bisal的个人杂货铺”,长期坚持分享技术文章,多次在线上和线下分享技术主题。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 900 字,预计阅读需要 3 分钟。
同事问了个问题,MySQL 的某个测试库,发现有这种情况:
- 给已设置为主键的列又加了一次索引,如下前两条 SQL 语句。
- 给同一个字段加了 2 次索引,如下后两条 SQL 语句。
# 情况 1 ALTER TABLE test ADD PRIMARY KEY USING BTREE(ID); ALTER TABLE test ADD INDEX idx_test01 USING BTREE(ID); # 情况 2 ALTER TABLE test ADD INDEX idx_test02 USING BTREE(UPDATED): ALTER TABLE test ADD INDEX idx_test03 USING BTREE(UPDATED);
正常情况只需要一条 SQL 就行?
这种情况是不是没有意义?
这两个问题考察的都是关于索引的基础知识,如果对此很熟悉,答案不言自明,即使不熟悉,只需要做些简单的测试,就可以了解,加深印象。
测试一
数据库版本:MySQL 8.0,为表 t
设置主键,再对同字段加个索引可以执行成功。
alter table t add primary key using btree(id); alter table t add index idx_t_id using btree(id);
对字段 c1
创建两个索引,都可以执行成功。
alter table tbl add index idx_t_001 using btree(c1); alter table tbl add index idx_t_002 using btree(c1);
以上实验说明:MySQL 中可以对相同的字段创建多次相同的索引。
测试二
通过 explain
,可以验证出对于同时存在 PRIMARY KEY 和普通索引的字段作为检索条件时,优化器会选择 PRIMARY KEY 作为 key,这种选择应该和 MySQL 以索引组织表存储的形式有关,对于同时存在两个索引名称的相同字段作为检索条件时,优化器会选择先创建的索引作为 key,这倒是很像 Oracle 中 RBO 对于索引选择的顺序判断逻辑(可能有些不严谨,但是因为完全是两个相同的索引(Oracle 终不会允许此种情况),cost 应该完全一致,所以选择谁,好像无所谓)。
bisal@mysqldb 13:02: [test]> explain select * from tbl where id=1; +----+-------------+-------+------------+-------+------------------+---------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+------------------+---------+---------+-------+------+----------+-------+ | 1 | SIMPLE | tbl | NULL | const | PRIMARY,idx_t_id | PRIMARY | 4 | const | 1 | 100.00 | NULL | +----+-------------+-------+------------+-------+------------------+---------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.07 sec) bisal@mysqldb 13:03: [test]> explain select * from tbl where c1='a'; +----+-------------+-------+------------+------+---------------------+-----------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------------+-----------+---------+-------+------+----------+-------+ | 1 | SIMPLE | tbl | NULL | ref | idx_t_001,idx_t_002 | idx_t_001 | 7 | const | 3 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------------+-----------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
以上实验说明 MySQL 对于相同字段的相同索引选择方面的逻辑。
测试三
从效果上看,这两个索引,保留一个即可,因为这两个索引只是名称不同,索引字段相同的,实际上就是相同的索引。
ALTER TABLE test ADD INDEX idx_test02 USING BTREE(UPDATED): ALTER TABLE test ADD INDEX idx_test03 USING BTREE(UPDATED);
但对于主键和索引的这两个,需要用主键这个。因为这两个最主要的区别就是主键除了包含索引外,还需保证唯一,而此处的索引,就是普通索引,不是唯一索引,因此从逻辑上,这两个是不等价。但是由于主键包含了索引,因此可以删除第二个索引,它属于重复的,主键的定义包含了索引的定义。
ALTER TABLE test ADD PRIMARY KEY USING BTREE(ID); ALTER TABLE test ADD INDEX idx_test01 USING BTREE(ID);
MySQL 之所以存在上面的这些问题,因为它允许创建不同名称相同索引字段的索引,但是如果是 Oracle,情况会是相同?
Oracle 19c,在主键字段上创建索引,会提示 此列列表已索引 的错误。在相同字段上创建第二个索引,也是提示 此列列表已索引 的错误。说明 Oracle 中根本不允许同一个字段存在两个相同索引的情况。
总结
因此只能说不同的数据库,设计理念不同,Oracle 更严谨些,MySQL 的容错性鲁棒性更突出(可能不太准确)。使用的时候,需要对这些基础能够有所了解,才可以针对合适的场景选择合适的操作。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
SQLE 获取

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
开源模型 Zephyr-7B🪁发布 —— 跨越三大洲的合作
最近我们刚刚发布了新的开源模型 Zephry-7B🪁, 这个模型的诞生离不开全球三大洲开源社区的协作 ❤️。 我们的 CSO Thomas 录了一个视频介绍了它的起源故事。 ✨ 就在几个月前,巴黎的一个新团队发布了他们首个模型: Mistral 7B,这个模型体积小巧但性能强劲,在基准测试中的表现超过了所有同类模型。而且这是个开源模型,这意味着大家都可以在此基础上进行开发。 ✨ 开发者 Lewis 在瑞士伯尔尼,Ed 在法国南部里昂,他们俩都是 Hugging Face H4 团队的一员。在 Hugging Face 举办的一次小聚中,他们边喝咖啡边讨论用斯坦福大学新发表的 DPO 方法对模型进行微调的可能性。于是大家决定用他们已经构建好的代码库来尝试一下💪 ✨接下来的一天,他们在 HF hub 上找到了一些公开的数据集,主要是由清华的 OpenBMB 团队新近开源的两个大型、高质量的微调数据集: UltraFeedback 和 UltraChat 📊 ✨ 经过几轮训练实验,他们的想法得到了证实: 这个新模型非常强大,在伯克利和斯坦福的基准测试中是他们见过的最强模型。Clémen...
- 下一篇
万字解析XML配置映射为BeanDefinition的源码
本文分享自华为云社区《Spring高手之路16——解析XML配置映射为BeanDefinition的源码》,作者:砖业洋__。 1. BeanDefinition阶段的分析 Spring框架中控制反转(IOC)容器的BeanDefinition阶段的具体步骤,主要涉及到Bean的定义、加载、解析,并在后面进行编程式注入和后置处理。这个阶段是Spring框架中Bean生命周期的早期阶段之一,对于理解整个Spring框架非常关键。 加载配置文件、配置类 在这一步,Spring容器通过配置文件或配置类来了解需要管理哪些Bean。对于基于XML的配置,通常使用ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext。 解析配置文件、配置类并封装为BeanDefinition Spring框架通过使用BeanDefinitionReader实例(如XmlBeanDefinitionReader)来解析配置文件。解析后,每个Bean配置会被封装成一个BeanDefinition对象,这个对象包含了类名、作用域、生命周期回调等信息...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Mario游戏-低调大师作品
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境