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

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

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

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

mysql> use testmysql> create table test_data2 (id int ,name varchar(30));Query OK, 0 rows affected (0.05 sec)
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
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)
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)
mysql> show create table test_data2\G*************************** 1. row ***************************    Table: test_data2Create 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=utf81 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;
mysql> show create table test_data3\G    *************************** 1. row ***************************    Table: test_data3Create 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=utf81 row in set (0.00 sec)
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`));
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优化器确定使用哪个索引的优先级。

更多相关文章

  1. 【Android(安卓)内存优化】Bitmap 内存缓存 ( Bitmap 内存复用 |
  2. Android内存管理策略的优化
  3. Android上的Open×××-TAP模式/策略路由
  4. Android(安卓)Design Demo 策略模式 TextView HTML封装 加下划线
  5. 谈电信运营商在Android产业链主导权的策略
  6. Android中的设计模式(结合大话设计模式+网上博客)
  7. Android第三方异步网路加载库AsyncHttpClient内部实现缓存策略了
  8. Android进行设备管理(针对企业开发)
  9. Android进行设备管理(针对企业开发)

随机推荐

  1. android控件之ImageButton android:scale
  2. android布局居中
  3. android:各种访问权限Permission
  4. android消息处理机制学习(一)-Handler,Mess
  5. android 二 BMI 小例子
  6. Android 3.0 r1 API中文文档(107) —— A
  7. android aapt (android asset packaging t
  8. [置顶] Android 5.1 open data flow 数据
  9. Android 3.1 r1 中文API文档 (120) ——
  10. Android客户端与服务器用Socket进行通信