MySQL的主键命名策略相关

最近在梳理数据生命周期管理的细节时,发现了一个小问题,那就是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`)
);

查看主键命名方法5:使用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'

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

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

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

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

  • 一个表只能有一个PRIMARY KEY。
  • PRIMARY KEY的名称始终为PRIMARY,因此不能用作任何其他类型的索引的名称。
  • 如果您没有PRIMARY KEY,而应用程序要求您在表中提供PRIMARY KEY,则MySQL将返回没有NULL列的第一个UNIQUE索引作为PRIMARY KEY。
  • 在InnoDB表中,将PRIMARY KEY保持较短,以最小化辅助索引的存储开销。每个辅助索引条目都包含对应行的主键列的副本。
  • 在创建的表中,首先放置一个PRIMARY KEY,然后放置所有UNIQUE索引,然后放置非唯一索引,这有助于MySQL优化器确定使用哪个索引的优先级,还可以更快地检测重复的UNIQUE键。

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

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

const char *primary_key_name="PRIMARY";

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

小结:

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

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

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

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

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

以上就是MySQL的主键命名策略相关的详细内容,更多关于MySQL 主键命名策略的资料请关注我们其它相关文章!

(0)

相关推荐

  • 深入分析mysql为什么不推荐使用uuid或者雪花id作为主键

    前言:在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究竟有什么坏处?本篇博客我们就来分析这个问题,探讨一下内部的原因. 一:mysql和程序实例 1.1:要说明这个问题,我们首先来建立三张表,分别是user_auto_key,user_uuid,user_random_key,分别表示自动增长的主键,uuid作为主键,随机

  • Mysql主键和唯一键的区别点总结

    什么是主键? 主键是表中唯一标识该表中每个元组(行)的列.主键对表实施完整性约束.表中只允许使用一个主键.主键不接受任何重复值和空值.表中的主键值很少更改,因此在选择主键是需要小心,要选择很少发生更改的地方.一个表的主键可以被另一个表的外键引用. 为了更好地理解主键,我们创建一个名为Student的表,它具有roll_number.name.batch.phone_number.citizen_id等属性. 在上面的示例中,roll_number属性永远不能具有相同的NULL值,因为在每个大学中

  • MySQL中主键与rowid的使用陷阱总结

    前言 大家在MySQL中我们可能听到过rowid的概念,但是却很难去测试实践,不可避免会有一些疑惑,比如: 如何感受到rowid的存在: rowid和主键有什么关联关系: 在主键的使用中存在哪些隐患: 如何来理解rowid的潜在瓶颈并调试验证. 本文要和大家一起讨论这几个问题,测试的环境基于MySQL 5.7.19版本. 问题1.如何感受到rowid的存在 我们不妨通过一个案例来进行说明. 记得有一天统计备份数据的时候,写了一条SQL,当看到执行结果时才发现SQL语句没有写完整,在完成统计工作之

  • 详解MySQL 表中非主键列溢出情况监控

    今天,又掉坑了. 之前踩到过MySQL主键溢出的情况,通过prometheus监控起来了,具体见这篇MySQL主键溢出复盘 这次遇到的坑,更加的隐蔽. 是一个log表里面的一个int signed类型的列写满了.快速的解决方法当然还是只能切新表来救急了,然后搬迁老表的部分历史数据到热表. 亡羊补牢,处理完故障后,赶紧写脚本把生产的其他表都捋一遍. 下面是我暂时用的一个检测脚本,还不太完善,凑合用 分2个文件(1个sql文件,1个shell脚本) check.sql 内容如下: SELECT ca

  • 浅谈MySQL中的自增主键用完了怎么办

    在面试中,大家应该经历过如下场景 面试官:"用过mysql吧,你们是用自增主键还是UUID?" 你:"用的是自增主键" 面试官:"为什么是自增主键?" 你:"因为采用自增主键,数据在物理结构上是顺序存储,性能最好,blabla-" 面试官:"那自增主键达到最大值了,用完了怎么办?" 你:"what,没复习啊!!"    (然后,你就可以回去等通知了!) 这个问题是一个粉丝给我提的,我觉得

  • spring boot整合mybatis利用Mysql实现主键UUID的方法

    前言 本文主要给大家介绍了关于spring boot整合mybatis利用Mysql实现主键UUID的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实现 基础项目的pom.xml部分代码如下 <properties> <java.version>1.8</java.version> </properties> <!-- Inherit defaults from Spring Boot --> <parent&

  • 使用prometheus统计MySQL自增主键的剩余可用百分比

    最近生产环境一套数据库因为疯狂写日志数据,造成主键值溢出的情况出现,因此有必要将这个指标监控起来. mysqld_exporter自带的这个功能,下面是我使用的启动参数: nohup ./mysqld_exporter --config.my-cnf="./my.cnf" --web.listen-address=":9104" --collect.heartbeat --collect.auto_increment.columns --collect.binlog

  • mysql非主键自增长用法实例分析

    本文实例讲述了mysql非主键自增长用法.分享给大家供大家参考,具体如下: mysql并非只有主键才能自增长,而是设为键的列就可以设置自增长.   如下: CREATE TABLE t1 ( id INT, col1 INT auto_increment NOT NULL ); 结果如下: 如果把col1列设为键,就可以创建自增. CREATE TABLE t1 ( id INT, col1 INT auto_increment NOT NULL, key(col1) ); 结果如下: 如果我们

  • MySQL的自增ID(主键) 用完了的解决方法

    在 MySQL 中用很多类型的自增 ID,每个自增 ID 都设置了初始值.一般情况下初始值都是从 0 开始,然后按照一定的步长增加(一般是自增 1).一般情况下,我们都是用int(11)来作为数据表的自增 ID,在 MySQL 中只要定义了这个数的字节长度,那么就会有上限. MySQL的自增ID(主键) 用完了,怎么办? 如果用 int unsigned (int,4个字节 ), 我们可以算下最大当前声明的自增ID最大是多少,由于这里定义的是 int unsigned,所以最大可以达到2的32幂

  • Python3 操作 MySQL 插入一条数据并返回主键 id的实例

    Python 中貌似并没有直接返回插入数据 id 的操作(反正我是没找到),但是我们可以变通一下,找到最新插入的数据 #!/usr/bin/env python3 # -*- coding: UTF-8 -*- import pymysql db = pymysql.connect(**db_conf) cursor = db.cursor() cursor.execute(sql) # 最后插入行的主键id print(cursor.lastrowid) # 最新插入行的主键id print(

随机推荐