当前位置: 首页 > news >正文

MySQL的主键命名挺任性,就这么定了

    这是学习笔记的第 2166 篇文章

  最近在梳理数据生命周期管理的细节时,发现了一个小问题,那就是MySQL的主键命名策略,似乎会忽略任何形式的自定义命名。

  也就意味着你给主键命名为idx_pk_id这种形式,在MySQL里面会统一按照PRIMARY来处理。 

  当然我们可以在这个基础之上做一些拓展和补充。 

  

  首先来复现下问题,我们连接到数据库test,然后创建表test_data2.

mysql> use test

mysql> create table test_data2 (id int ,name varchar(30));

Query OK, 0 rows affected (0.05 sec)

接着创建一个主键,命名为idx_pk_id,从执行情况来看,MySQL是正常处理了。

mysql> alter table test_data2 add primary key idx_pk_id(id);

Query OK, 0 rows affected (0.02 sec)

Records: 0  Duplicates: 0  Warnings: 0

为了进一步对比,我们添加一个唯一性索引(辅助索引),来看看它们的差异。

mysql> alter table test_data2 add unique key idx_uniq_name(name);

Query OK, 0 rows affected (0.00 sec)

Records: 0  Duplicates: 0  Warnings: 0

查看主键命名方法1:使用show indexes命令

要查看MySQL索引的信息,使用show indexes from test_data2就可以。

mysql> show indexes from test_data2\G

*************************** 1. row ***************************

        Table: test_data2

   Non_unique: 0

     Key_name: PRIMARY

 Seq_in_index: 1

  Column_name: id

    Collation: A

  Cardinality: 0

     Sub_part: NULL

       Packed: NULL

         Null: 

   Index_type: BTREE

      Comment: 

Index_comment: 

*************************** 2. row ***************************

        Table: test_data2

   Non_unique: 0

     Key_name: idx_uniq_name

 Seq_in_index: 1

  Column_name: name

    Collation: A

  Cardinality: 0

     Sub_part: NULL

       Packed: NULL

         Null: YES

   Index_type: BTREE

      Comment: 

Index_comment: 

2 rows in set (0.00 sec)

查看主键命名方法2:使用数据字典information_schema.statistics

使用命令的方式不够通用,我们可以使用数据字典information_schema.statistics来进行数据提取。

mysql> select *from information_schema.statistics where table_schema='test' and table_name='test_data2' limit 20 \G                

*************************** 1. row ***************************

TABLE_CATALOG: def

 TABLE_SCHEMA: test

   TABLE_NAME: test_data2

   NON_UNIQUE: 0

 INDEX_SCHEMA: test

   INDEX_NAME: PRIMARY

 SEQ_IN_INDEX: 1

  COLUMN_NAME: id

    COLLATION: A

  CARDINALITY: 0

     SUB_PART: NULL

       PACKED: NULL

     NULLABLE: 

   INDEX_TYPE: BTREE

      COMMENT: 

INDEX_COMMENT: 

*************************** 2. row ***************************

TABLE_CATALOG: def

 TABLE_SCHEMA: test

   TABLE_NAME: test_data2

   NON_UNIQUE: 0

 INDEX_SCHEMA: test

   INDEX_NAME: idx_uniq_name

 SEQ_IN_INDEX: 1

  COLUMN_NAME: name

    COLLATION: A

  CARDINALITY: 0

     SUB_PART: NULL

       PACKED: NULL

     NULLABLE: YES

   INDEX_TYPE: BTREE

      COMMENT: 

INDEX_COMMENT: 

2 rows in set (0.00 sec)

查看主键命名方法3:使用show create table 命令

如果查看建表语句,会发现主键名已经被过滤掉了。

mysql> show create table test_data2\G

*************************** 1. row ***************************

       Table: test_data2

Create Table: CREATE TABLE `test_data2` (

  `id` int(11) NOT NULL,

  `name` varchar(30) DEFAULT NULL,

  PRIMARY KEY (`id`),

  UNIQUE KEY `idx_uniq_name` (`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

1 row in set (0.00 sec)

有的同学可能想,是不是分别执行了create,alter语句导致处理方式有差异,我们可以一步到位,在create语句里面声明主键名。

CREATE TABLE `test_data3` (

  `id` int(11) NOT NULL,

  `name` varchar(30) DEFAULT NULL,

  PRIMARY KEY idx_pk_id(`id`),

  UNIQUE KEY `idx_uniq_name` (`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这个时候查看建表语句,会发现结果和上面一样,主键名都是PRIMARY.

mysql> show create table test_data3\G       

*************************** 1. row ***************************

       Table: test_data3

Create Table: CREATE TABLE `test_data3` (

  `id` int(11) NOT NULL,

  `name` varchar(30) DEFAULT NULL,

  PRIMARY KEY (`id`),

  UNIQUE KEY `idx_uniq_name` (`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

1 row in set (0.00 sec)

查看主键命名方法4:查看约束命名

当然还有多种验证方式,比如我们使用约束的方式来命名,得到的主键名都是PRIMARY.

CREATE TABLE IF NOT EXISTS `default_test` (

 `default_test`.`id` SMALLINT NOT NULL AUTO_INCREMENT,

 `default_test`.`name` LONGTEXT NOT NULL,

CONSTRAINT `pk_id` PRIMARY KEY (`id`)

);

查看主键命名方法4:使用DML报错信息

当然还有其他多种形式可以验证,比如我们使用DML语句。

mysql> insert into test_data2 values(1,'aa');

Query OK, 1 row affected (0.02 sec)

mysql> insert into test_data2 values(1,'aa');

ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

以上的方法都可以让我们对这个细节有更深入的理解,当然我们可以再深入一些。 

查看主键命名方法5:官方文档

官方文档里面其实包含了这个信息,但是不是很明显。

关于主键的描述,大体内容如下,有一条是专门做了声明,主键名为PRIMARY.

  • 一个表只能有一个PRIMARY KEY。 

  • PRIMARY KEY的名称始终为PRIMARY,因此不能用作任何其他类型的索引的名称。

  • 如果您没有PRIMARY KEY,而应用程序要求您在表中提供PRIMARY KEY,则MySQL将返回没有NULL列的第一个UNIQUE索引作为PRIMARY KEY。

  • 在InnoDB表中,将PRIMARY KEY保持较短,以最小化辅助索引的存储开销。每个辅助索引条目都包含对应行的主键列的副本。

  • 在创建的表中,首先放置一个PRIMARY KEY,然后放置所有UNIQUE索引,然后放置非唯一索引,这有助于MySQL优化器确定使用哪个索引的优先级,还可以更快地检测重复的UNIQUE键。

查看主键命名方法6:源代码

在sql_table.cc 里面对主键名称做了定义声明。

const char *primary_key_name="PRIMARY";

顺着这条路,可以看到在不同层的实现中的一些逻辑情况。

小结:

通过这样的一些方式,我们对主键的命名情况有了一个整体的认识,为什么会采用PRIMARY这样一个命名呢,我总结了几点:

1)统一命名可以理解是一种规范

2)和唯一性索引能够区别开来,比如一个唯一性索引非空,从属性上来看很相似的,通过主键命名就可以区分出来,在一些特性和索引使用场景中也容易区分。

3)主键是一个表索引的第一个位置,统一命名可以在逻辑判断中更加清晰,包括字段升级为主键的场景等等。 

4)在优化器处理中也会更加方便,提高MySQL优化器确定使用哪个索引的优先级。

近期热文:

迁移到MySQL的业务架构演进实战

数据库修改密码风险高,如何保证业务持续,这几种密码双活方案可以参考

MySQL业务双活的初步设计方案

如何优化MySQL千万级大表,我写了6000字的解读

一道经典的MySQL面试题,答案出现三次反转

业务双活的数据切换思路设计(下)

业务双活的数据切换思路设计(一)

MySQL中的主键和rowid,看似简单,其实有一些使用陷阱需要注意

小白学MySQL要多久?我整理了10多个问题的答案

转载热文:

《吊打面试官》系列-Redis基础

唯一ID生成算法剖析,看看这篇就够了

关于大数据运维能力的一些思考

DBA菜鸟的进化简史:不忘初心,记工作中踩过的三个坑

美女主持直播,被突发意外打断!湾区网友却高喊: 我懂!超甜

QQ群号:763628645

QQ群二维码如下, 添加请注明:姓名+地区+职位,否则不予通过

在看,让更多人看到

相关文章:

  • 运维开发和测试中常见的8个问题
  • MySQL数据清理有技巧,这么破
  • 《奇葩说》救猫还是救画,我做了认真的分析
  • 程序员开发效率神器汇总!
  • 瞎忙之余的一些小结
  • 关于高可用,我们关注得好像有点窄
  • 去IOE or Not?
  • 拉里·佩奇(Larry Page)的伟大归来
  • Linux系统——架构浅析
  • 解码Redis最易被忽视的CPU和内存占用高问题
  • 还能这样?把 Python 自动翻译成 C++
  • 华裔教授发现二次方程极简解法,我默默的做了下验算
  • 运维系统性能优化后思考,除了避免懒惰的麻木,还需要了解系统的“脾性”...
  • 用python重新定义【2019十大网络流行语】
  • 那些对我来说没有价值和有价值的事情
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 07.Android之多媒体问题
  • Angular 4.x 动态创建组件
  • fetch 从初识到应用
  • java多线程
  • jquery cookie
  • Mysql5.6主从复制
  • Quartz初级教程
  • React-redux的原理以及使用
  • tensorflow学习笔记3——MNIST应用篇
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • underscore源码剖析之整体架构
  • vue-router的history模式发布配置
  • windows-nginx-https-本地配置
  • 基于axios的vue插件,让http请求更简单
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 听说你叫Java(二)–Servlet请求
  • 王永庆:技术创新改变教育未来
  • 我这样减少了26.5M Java内存!
  • 学习使用ExpressJS 4.0中的新Router
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ​如何在iOS手机上查看应用日志
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • #单片机(TB6600驱动42步进电机)
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (七)c52学习之旅-中断
  • (四)鸿鹄云架构一服务注册中心
  • (转)C#调用WebService 基础
  • (转)Mysql的优化设置
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET Micro Framework初体验
  • .NET 依赖注入和配置系统
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .netcore如何运行环境安装到Linux服务器
  • /bin、/sbin、/usr/bin、/usr/sbin