Mysql auto_increment总结
一、为什么InnoDB表要建议用自增列做主键
我们先了解下InnoDB引擎表的一些关键特征:
- InnoDB引擎表是基于B+树的索引组织表(IOT);
- 每个表都需要有一个聚集索引(clustered index);
- 所有的行记录都存储在B+树的叶子节点(leaf pages of the tree);
- 基于聚集索引的增、删、改、查的效率相对是最高的;
- 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择其作为聚集索引;
- 如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引;
- 如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。
综上总结,如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的,也就是下面这几种情况的存取效率最高:
- 使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;
- 该表不指定自增列做主键,同时也没有可以被选为主键的唯一索引(上面的条件),这时候InnoDB会选择内置的ROWID作为主键,写入顺序和ROWID增长顺序一致;
- 除此以外,如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。
实际情况是如何呢?经过简单TPCC基准测试,修改为使用自增列作为主键与原始表结构分别进行TPCC测试,前者的TpmC结果比后者高9%倍,足见使用自增列做InnoDB表主键的明显好处,其他更多不同场景下使用自增列的性能提升可以自行对比测试下。
注意:同时推荐使用UNSIGNED自增列作为主键。
- DROP TABLE IF EXISTS `test_auto_increment`;
- CREATE TABLE `test_auto_increment` (
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
- `name` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
二、mysql获取自增ID的最大值
mysql插入数据后返回自增ID的方法,last_insert_id(),selectkey
在关系型数据库的表结构中,一般情况下,都会定义一个具有‘AUTO_INCREMENT’扩展属性的‘ID’字段,以确保数据表的每一条记录都有一个唯一标识。
而实际应用中,获取到最近最大的ID值是必修课之一,针对于该问题,实践整理如下:
1、新建测试数据表get_max_id
- -- ----------------------------
- -- Table structure for test_auto_increment
- -- ----------------------------
- DROP TABLE IF EXISTS `test_auto_increment`;
- CREATE TABLE `test_auto_increment` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
2、未初始化表获取最大自增ID
创建完数据表之后,我们知道,表中的内容暂时为空,此时,查询max(id)获取到的内容将是NULL;
方式1 - max(id):
该方式的优点是简单粗暴,直奔主题;
同时,它无视其它客户端连接(db_connection)的影响,可以直奔第3点位置;
- select max(id) from test_auto_increment;
方式2 - LAST_INSERT_ID()函数:
LAST_INERT_ID(),返回最后一个INSERT或 UPDATE 查询中, AUTO_INCREMENT列设置的第一个表的值。
这玩意儿的使用还是有些限制的:
1、同一个Connection连接对象(同一客户端)中,SELECT的结果为最后一次INSERT的AUTO_INCREMENT属性列的ID。这句话的重点在于“同一个”,即其他连接的客户端不对其查询的结果造成影响。假设客户端A和B,表ta原自增ID为3,在A中插入记录后产生自增ID为4,在客户端A中通过该函数查询的结果为4,但在客户端B中查询的结果值仍为3;(已验证)
2、与表无关,即假设ta表和tb表,向ta插入记录后,再向tb插入记录,结果值为tb的max(id)值;(已验证)
3、使用非魔术方法(‘magic‘)来INSERT或UPDATE一条记录时,即使用非0/非NULL值作为插入的字段,则LAST_INSERT_ID()返回值不会发生变化;(已验证)
4、同一条INSERT语句中,传入多个VALUES值,则LAST_INSERT_ID()返回值为该查询第一条记录的ID;(已验证)
5、在进阶方面,可运用作分表ID的唯一性。
初始化查询的结果,得到的是0,这点和max(id)还是有区别的;
- mysql>select LAST_INSERT_ID();
- +------------------+
- | LAST_INSERT_ID() |
- +------------------+
- | 0 |
- +------------------+
- 1 row in set (0.00 sec)
方式3 - 查看表状态show table status
该方式提供了当前DB(use db_name;)下每个表的基本信息;可以通过where条件获取到Auto_increment属性的值;
下述提供的结果值,为下一个自增ID的数值。
- mysql> show table status where Name=‘get_max_id‘;
- +------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
- | Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options| Comment |
- +------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
- | get_max_id | InnoDB | 10 | Compact | 0 | 0 | 16384 | 0 | 0 | 10485760 | 1 | 2015-04-20 11:49:07 | NULL | NULL | utf8_general_ci | NULL | | |
- +------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
- 1 row in set (0.00 sec)
方式4 - information_schema.tables
提供关于数据库中的表(包括视图)的信息。详细描述了某个表属于哪个schema,表类型,表引擎等等信息;
下述提供的结果值,为下一个自增ID的数值。
- mysql> select table_name, AUTO_INCREMENT from information_schema.tables where table_name="get_max_id";
- +------------+----------------+
- | table_name | AUTO_INCREMENT |
- +------------+----------------+
- | get_max_id | 1 |
- +------------+----------------+
- 1 row in set (0.01 sec)
方式5 - @@IDENTITY全局变量
基础:以@@开头的变量为全局变量,而以@开头的变量为用户自定义的变量。
此处 @@IDENTITY表示最近一次向具有identity属性(auto_increment)的表INSERT数据时对应的自增列的值。此处得到的值是0。
1、类似于LAST_INSERT_ID()函数,该方式必须在同一个客户端内进行的INSERT与SELECT,且不受其他客户端影响;(已验证)
2、与表无关;(已验证)
3、非魔术方法插入不影响结果值;(已验证)
4、同一INSERT插入多条记录,取第一条记录的ID值为结果;(已验证)
- mysql> select @@IDENTITY;
- +------------+
- | @@IDENTITY |
- +------------+
- | 0 |
- +------------+
- 1 row in set (0.00 sec)
三、自增ID在服务器重启后会根据表中当前最大值重新计算
验证如下:
1、先向测试表插入如下行
2、删除2-6的行,再插入新的7行数据,如下所示,ID继续增长
3、删除最后的5行数据
4、重启mysql
5、插入新的数据
Mysql auto_increment总结的更多相关文章
- [MySQL] AUTO_INCREMENT lock Handing in InnoDB
MySQL AUTO_INCREMENT lock Handing in InnoDB 在MySQL的表设计中很普遍的使用自增长字段作为表主键, 实际生产中我们也是这样约束业务开发同学的, 其中的优势 ...
- 验证:mysql AUTO_INCREMENT 默认值是1
用mongodb时,有些字段需要做自增,而且是用二十进制字母表示(使用a-t对应0-19),做了一个_auto_increment字段用来保存,但是应该从0开始还是从1开始呢? 和mysql保持一致便 ...
- MySQL Auto_Increment属性应用
我们经常要用到唯一编号,以标识记录.在MySQL中可通过数据列的AUTO_INCREMENT属性来自动生成.MySQL支持多种数据表,每种数据表的自增属性都有差异,这里将介绍各种数据表里的数据 ...
- MySQL auto_increment的坑
背景: Innodb引擎使用B_tree结构保存表数据,这样就需要一个唯一键表示每一行记录(比如二级索引记录引用). Innodb表定义中处理主键的逻辑是: 1.如果表定义了主键,就使用主键唯一定位一 ...
- MySQL AUTO_INCREMENT 简介
可使用复合索引在同一个数据表里创建多个相互独立的自增序列,具体做法是这样的:为数据表创建一个由多个数据列组成的PRIMARY KEY OR UNIQUE索引,并把AUTO_INCREMENT数据列包括 ...
- MySQL AUTO_INCREMENT 学习总结
之前有碰到过开发同事指出一张InnoDB表的自增列 AUTO_INCREMENT 值莫明的变大,由于这张表是通过mysqldump导出导入的. 问题排查: 1.首先,查看表表义的sql部分的 auto ...
- MySQL auto_increment介绍 以及 查询和修改auto_increment的方法
一.auto_increment使用方法 .创建table时设置auto_increment属性和初始值100 create table nonove ( id bigint unsigned not ...
- MySql: AUTO_INCREMENT
首先要在Column使用AUTO_INCREMENT (每张表只有一个列可以AUTO_INCREMENT): 以下示例取自MySql官网(http://dev.mysql.com/doc/refman ...
- MySQL auto_increment实现
http://www.cnblogs.com/xpchild/p/3825309.html 运维的时候,经常遇到auto_increment的疑惑: 机器异常crash,重启后id回退的问题 性能考虑 ...
随机推荐
- EasyUI Combobox 组合框
默认选择第一项,加请选择,取值问题 <input class="easyui-combobox" id="ddlWHS" name="ddlWH ...
- bzip2压缩 解压缩
压缩/解压缩压缩/解压缩之后的文件名称 必须是bz2 首先是 -z 压缩文件-d 解压缩!
- this指针逃逸问题
this指针逃逸是指在构造函数返回之前,其他线程已经就持有了该对象的应用,产生的结果自然和预期可能会产生差异.常见的this指针逃逸,在并发编程实战一书中,作者指出:在构造函数中注册事件监听,在构造函 ...
- va_start、va_arg、va_end、va_copy 可变参函数
1.应用与原理 在C语言中,有时我们无法给出一个函数参数的列表,比如: int printf(const char *format, ...); int fprintf(FILE *s ...
- weblogic、hibernate 包冲突
解决办法: 在weblogic 配置 [paths]项中 添加antlr-2.7.7.jar,该jar包应该位于引用weblogic.jar之前,使启动时不再加载weblogic中的低版本的antl ...
- 《gradle 用户指南中文版》目录
gradle 用户指南 版权所有©2007-2017 Hans Dockter,Adam Murdoch只要您不对这些副本收取任何费用,并且进一步规定,每个副本都包含本版权声明,无论是以印刷版还是电子 ...
- 几种常见的微服务架构方案——ZeroC IceGrid、Spring Cloud、基于消息队列、Docker Swarm
微服务架构是当前很热门的一个概念,它不是凭空产生的,是技术发展的必然结果.虽然微服务架构没有公认的技术标准和规范草案,但业界已经有一些很有影响力的开源微服务架构平台,架构师可以根据公司的技术实力并结合 ...
- [置顶]
普通程序员如何入门AI
毫无疑问,人工智能是目前整个互联网领域最火的行业,随着AlphaGo战胜世界围棋冠军,以及各种无人驾驶.智能家居项目的布道,人们已经意识到了AI就是下一个风口.当然,程序员是我见过对于新技术最敏感的一 ...
- Django:牛刀小试
牛刀小试 简谈Django 搭建开发环境 做一个简单的博客网站 写在开始之前: 要求:python基础.HTML基础.浏览器上网的基本原理 以下环境为:windows10专业版 64位 .Djan ...
- UDP:rfc768/广播和多播/IGMP
封装情况: