背景

之前面试的时候,有几家公司都问了UUID,自增ID的优点以及缺点,个人当时只考虑到了索引方面(增删查改的效率),没有考虑到分布式情况下的问题。

如果未来可能对数据进行合并、转移,自增ID势必会发生主键重复问题。

跨步自增可以解决分布式问题,但是需要对充分考虑好跨域的步数。

UUID可以解决分布式问题,但是因为是varchar类型并且又很长,影响索引重组速度,又会大大影响增删改效率(随数据量变大到百万千万级时会慢慢接近自增ID)。

雪花算法可以得出一个int类型的ID,此ID可以直接进行排序,可以解决分布式问题,但是生成时需要注意机器ID等参数,因为生成的int值很大,在小项目运用时也会影响主键索引重组。

总之,根据当前数据量大小,再预测未来的数据量,然后选择最合适的主键类型,像人员信息表这类数据,做大之后未来就极有可能会涉及分布式和合表问题。

另外,如果说有一种情况,某表内的数据一开始在某个系统里以自增为主键的时候,插入时顺便也生成一个UUID存放到一个临时字段里,数据转移时将此表内的数据和结构先克隆为另外一个新表,然后把新表的自增ID删除,将UUID那个字段设置成主键后再合并到新系统的表中,这样是不是即不影响之前的系统效率,也防止了分布式主键冲突的问题?


测试部分:

1、准备表以及数据

UC_USER,自增ID为主键,表结构类似如下:

CREATE TABLE `UC_USER` (`ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`USER_NAME` varchar(100) DEFAULT NULL COMMENT '用户名',`USER_PWD` varchar(200) DEFAULT NULL COMMENT '密码',`BIRTHDAY` datetime DEFAULT NULL COMMENT '生日',`NAME` varchar(200) DEFAULT NULL COMMENT '姓名',`USER_ICON` varchar(500) DEFAULT NULL COMMENT '头像图片',`SEX` char(1) DEFAULT NULL COMMENT '性别, 1:男,2:女,3:保密',`NICKNAME` varchar(200) DEFAULT NULL COMMENT '昵称',`STAT` varchar(10) DEFAULT NULL COMMENT '用户状态,01:正常,02:冻结',`USER_MALL` bigint(20) DEFAULT NULL COMMENT '当前所属MALL',`LAST_LOGIN_DATE` datetime DEFAULT NULL COMMENT '最后登录时间',`LAST_LOGIN_IP` varchar(100) DEFAULT NULL COMMENT '最后登录IP',`SRC_OPEN_USER_ID` bigint(20) DEFAULT NULL COMMENT '来源的联合登录',`EMAIL` varchar(200) DEFAULT NULL COMMENT '邮箱',`MOBILE` varchar(50) DEFAULT NULL COMMENT '手机',`IS_DEL` char(1) DEFAULT '0' COMMENT '是否删除',`IS_EMAIL_CONFIRMED` char(1) DEFAULT '0' COMMENT '是否绑定邮箱',`IS_PHONE_CONFIRMED` char(1) DEFAULT '0' COMMENT '是否绑定手机',`CREATER` bigint(20) DEFAULT NULL COMMENT '创建人',`CREATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间',`UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改日期',`PWD_INTENSITY` char(1) DEFAULT NULL COMMENT '密码强度',`MOBILE_TGC` char(64) DEFAULT NULL COMMENT '手机登录标识',`MAC` char(64) DEFAULT NULL COMMENT 'mac地址',`SOURCE` char(1) DEFAULT '0' COMMENT '1:WEB,2:IOS,3:ANDROID,4:WIFI,5:管理系统, 0:未知',`ACTIVATE` char(1) DEFAULT '1' COMMENT '激活,1:激活,0:未激活',`ACTIVATE_TYPE` char(1) DEFAULT '0' COMMENT '激活类型,0:自动,1:手动',PRIMARY KEY (`ID`),UNIQUE KEY `USER_NAME` (`USER_NAME`),KEY `MOBILE` (`MOBILE`),KEY `IDX_MOBILE_TGC` (`MOBILE_TGC`,`ID`),KEY `IDX_EMAIL` (`EMAIL`,`ID`),KEY `IDX_CREATE_DATE` (`CREATE_DATE`,`ID`),KEY `IDX_UPDATE_DATE` (`UPDATE_DATE`)
) ENGINE=InnoDB AUTO_INCREMENT=7122681 DEFAULT CHARSET=utf8 COMMENT='用户表'

UC_USER_PK_VARCHAR表,字符串ID为主键,采用uuid

CREATE TABLE `UC_USER_PK_VARCHAR_1` (`ID` varchar(36) CHARACTER SET utf8mb4 NOT NULL DEFAULT '0' COMMENT '主键',`USER_NAME` varchar(100) DEFAULT NULL COMMENT '用户名',`USER_PWD` varchar(200) DEFAULT NULL COMMENT '密码',`BIRTHDAY` datetime DEFAULT NULL COMMENT '生日',`NAME` varchar(200) DEFAULT NULL COMMENT '姓名',`USER_ICON` varchar(500) DEFAULT NULL COMMENT '头像图片',`SEX` char(1) DEFAULT NULL COMMENT '性别, 1:男,2:女,3:保密',`NICKNAME` varchar(200) DEFAULT NULL COMMENT '昵称',`STAT` varchar(10) DEFAULT NULL COMMENT '用户状态,01:正常,02:冻结',`USER_MALL` bigint(20) DEFAULT NULL COMMENT '当前所属MALL',`LAST_LOGIN_DATE` datetime DEFAULT NULL COMMENT '最后登录时间',`LAST_LOGIN_IP` varchar(100) DEFAULT NULL COMMENT '最后登录IP',`SRC_OPEN_USER_ID` bigint(20) DEFAULT NULL COMMENT '来源的联合登录',`EMAIL` varchar(200) DEFAULT NULL COMMENT '邮箱',`MOBILE` varchar(50) DEFAULT NULL COMMENT '手机',`IS_DEL` char(1) DEFAULT '0' COMMENT '是否删除',`IS_EMAIL_CONFIRMED` char(1) DEFAULT '0' COMMENT '是否绑定邮箱',`IS_PHONE_CONFIRMED` char(1) DEFAULT '0' COMMENT '是否绑定手机',`CREATER` bigint(20) DEFAULT NULL COMMENT '创建人',`CREATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间',`UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改日期',`PWD_INTENSITY` char(1) DEFAULT NULL COMMENT '密码强度',`MOBILE_TGC` char(64) DEFAULT NULL COMMENT '手机登录标识',`MAC` char(64) DEFAULT NULL COMMENT 'mac地址',`SOURCE` char(1) DEFAULT '0' COMMENT '1:WEB,2:IOS,3:ANDROID,4:WIFI,5:管理系统, 0:未知',`ACTIVATE` char(1) DEFAULT '1' COMMENT '激活,1:激活,0:未激活',`ACTIVATE_TYPE` char(1) DEFAULT '0' COMMENT '激活类型,0:自动,1:手动',PRIMARY KEY (`ID`),UNIQUE KEY `USER_NAME` (`USER_NAME`),KEY `MOBILE` (`MOBILE`),KEY `IDX_MOBILE_TGC` (`MOBILE_TGC`,`ID`),KEY `IDX_EMAIL` (`EMAIL`,`ID`),KEY `IDX_CREATE_DATE` (`CREATE_DATE`,`ID`),KEY `IDX_UPDATE_DATE` (`UPDATE_DATE`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';

2、500W数据测试

2.1 录入500W数据,自增ID节省一半磁盘空间

确定两个表数据量

# 自增id为主键的表mysql> select count(1) from UC_USER;+----------+| count(1) |+----------+|  5720112 |+----------+1 row in set (0.00 sec)mysql># uuid为主键的表mysql> select count(1) from UC_USER_PK_VARCHAR_1;+----------+| count(1) |+----------+|  5720112 |+----------+1 row in set (1.91 sec)

占据的空间容量来看,自增ID比UUID小一半左右。

主键类型

数据文件大小

占据容量 

自增ID

-rw-rw---- 1 mysql mysql 4.2G Aug 20 23:08 UC_USER_1.ibd

4.2 G

UUID

-rw-rw---- 1 mysql mysql 8.8G Aug 20 18:20 UC_USER_PK_VARCHAR_1.ibd

8.8 G

4.2 单个数据走索引查询,自增id和 uuid效率比是:(2~3):1

主键类型

SQL语句

执行时间 (秒)

单条记录查询

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`MOBILE` ='14782121512';

0.069

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` ='14782121512';

0.274

小范围查询

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`MOBILE` IN( '14782121512','13761460105');

0.050

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` IN('14782121512','13761460105');

0.151

根据日期查询

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE`='2013-11-24 10:26:36' ;

0.269

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE`='2013-11-24 10:26:43' ;

0.810

4.3 范围like查询,自增ID性能优于UUID,比值(1.5~2):1

主键类型

SQL语句

执行时间 (秒)

(1)模糊范围查询1000条数据,自增ID性能要好于UUID

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER` t WHERE t.`MOBILE` LIKE '147%' LIMIT 1000;

2.398

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` LIKE '147%' LIMIT 1000;

5.872

(2)日期范围查询20条数据,自增ID稍微弱于UUID

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE` > '2016-08-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 20;

0.765

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-08-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 20;

1.090

(3)范围查询200条数据,自增ID性能要好于UUID

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 200;

1.569

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 200;

2.597

范围查询总数量,自增ID要好于UUID

自增ID

SELECT SQL_NO_CACHE COUNT(1) FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36'  ;

1.129

UUID

SELECT SQL_NO_CACHE COUNT(1) FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36'  ;

2.302

4.4 写入测试,自增ID比UUID效率高,比值(3~10):1

主键类型

SQL语句

执行时间 (秒)

 

 

修改一天的记录

自增ID

UPDATE test.`UC_USER_1` t SET t.`MOBILE_TGC`='T2' WHERE t.`CREATE_DATE` > '2016-05-03 10:26:36' AND t.`CREATE_DATE` <'2016-05-04 00:00:00'  ;

2.685

UUID

UPDATE test.`UC_USER_PK_VARCHAR_1` t SET t.`MOBILE_TGC`='T2' WHERE t.`CREATE_DATE` > '2016-05-03 10:26:36' AND t.`CREATE_DATE` <'2016-05-04 00:00:00'  ;

26.521

录入数据

自增ID

INSERT INTO test.`UC_USER_1`(   ID,   `USER_NAME`,   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`,   `MOBILE`,   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` ) SELECT       NULL,    CONCAT('110',`USER_NAME`,8),   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`, CONCAT('110',TRIM(`MOBILE`)),   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` FROM `test`.`UC_USER_1` LIMIT 100;

0.534

UUID

INSERT INTO test.`UC_USER_PK_VARCHAR_1`(    ID,   `USER_NAME`,   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`,   `MOBILE`,   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` ) SELECT         UUID(),   CONCAT('110',`USER_NAME`,8),   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`, CONCAT('110',TRIM(`MOBILE`)),   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` FROM `test`.`UC_USER_1` LIMIT 100;

1.716

4.5、备份和恢复,自增ID性能优于UUID

主键类型

SQL语句

执行时间 (秒)

 

Mysqldump备份

自增ID

time mysqldump -utim -ptimgood -h192.168.121.63 test UC_USER_1> UC_USER_1.sql

0m50.548s

UUID

time mysqldump -utim -ptimgood -h192.168.121.63 test UC_USER_PK_VARCHAR_1> UC_USER_PK_VARCHAR_1.sql

0m58.590s

 

MySQL恢复

自增ID

time mysql -utim -ptimgood -h192.168.121.63 test < UC_USER_1.sql

17m30.822s

UUID

time mysql -utim -ptimgood -h192.168.121.63 test < UC_USER_PK_VARCHAR_1.sql

23m6.360s

 

 

 

5、1000W总结

在1000W记录表的测试下:

(1)普通单条或者20条左右的记录检索,自增主键效率是uuid主键的2到3倍;

(2)但是范围查询特别是上百成千条的记录查询,自增id的效率要大于uuid;

(3)在范围查询做统计汇总的时候,自增id主键的效率是uuid主键1.5到2倍;

(4)在存储上面,自增id所占的存储空间是uuid的1/2;

(5)在写入上面,自增ID主键的效率是UUID主键的3到10倍,相差比较明显,特别是update小范围之内的数据上面。

(6)在备份恢复上,自增ID主键稍微优于UUID。

6、MySQL分布式架构的取舍

分布式架构,意味着需要多个实例中保持一个表的主键的唯一性。这个时候普通的单表自增ID主键就不太合适,因为多个mysql实例上会遇到主键全局唯一性问题。

6.1、自增ID主键+步长,适合中等规模的分布式场景

在每个集群节点组的master上面,设置(auto_increment_increment),让目前每个集群的起始点错开 1,步长选择大于将来基本不可能达到的切分集群数,达到将 ID 相对分段的效果来满足全局唯一的效果。

优点是:实现简单,后期维护简单,对应用透明。

缺点是:第一次设置相对较为复杂,因为要针对未来业务的发展而计算好足够的步长;

规划:

比如计划总共N个节点组,那么第i个节点组的my.cnf的配置为:

auto_increment_offset  i

auto_increment_increment  N

假如规划48个节点组,N为48,现在配置第8个节点组,这个i为8,第8个节点组的my.cnf里面的配置为:

auto_increment_offset  8

auto_increment_increment  48

6.2、UUID,适合小规模的分布式环境

对于InnoDB这种聚集主键类型的引擎来说,数据会按照主键进行排序,由于UUID的无序性,InnoDB会产生巨大的IO压力,而且由于索引和数据存储在一起,字符串做主键会造成存储空间增大一倍。

在存储和检索的时候,innodb会对主键进行物理排序,这对auto_increment_int是个好消息,因为后一次插入的主键位置总是在最后。但是对uuid来说,这却是个坏消息,因为uuid是杂乱无章的,每次插入的主键位置是不确定的,可能在开头,也可能在中间,在进行主键物理排序的时候,势必会造成大量的 IO操作影响效率,在数据量不停增长的时候,特别是数据量上了千万记录的时候,读写性能下降的非常厉害。

优点:搭建比较简单,不需要为主键唯一性的处理。

缺点:占用两倍的存储空间(在云上光存储一块就要多花2倍的钱),后期读写性能下降厉害。

6.3、雪花算法自造全局自增ID,适合大数据环境的分布式场景

由twitter公布的开源的分布式id算法snowflake(Java版本)

IdWorker.java:

package com.demo.elk;import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class IdWorker {protected static final Logger LOG = LoggerFactory.getLogger(IdWorker.class);private long workerId;private long datacenterId;private long sequence = 0L;private long twepoch = 1288834974657L;private long workerIdBits = 5L;private long datacenterIdBits = 5L;private long maxWorkerId = -1L ^ (-1L << workerIdBits);private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);private long sequenceBits = 12L;private long workerIdShift = sequenceBits;private long datacenterIdShift = sequenceBits + workerIdBits;private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private long sequenceMask = -1L ^ (-1L << sequenceBits);private long lastTimestamp = -1L;public IdWorker(long workerId, long datacenterId) {// sanity check for workerIdif (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;LOG.info(String.format("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId));}public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {LOG.error(String.format("clock is moving backwards.  Rejecting requests until %d.", lastTimestamp));throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;}protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}protected long timeGen() {return System.currentTimeMillis();}}

测试生成ID的测试类,IdWorkerTest.java:

package com.demo.elk;

import java.util.HashSet;

import java.util.Set;

public class IdWorkerTest {

static class IdWorkThread implements Runnable {

private Set<Long> set;

private IdWorker idWorker;

public IdWorkThread(Set<Long> set, IdWorker idWorker) {

this.set = set;

this.idWorker = idWorker;

}

public void run() {

while (true) {

long id = idWorker.nextId();

System.out.println("            real id:" + id);

if (!set.add(id)) {

System.out.println("duplicate:" + id);

}

}

}

}

public static void main(String[] args) {

Set<Long> set = new HashSet<Long>();

final IdWorker idWorker1 = new IdWorker(0, 0);

final IdWorker idWorker2 = new IdWorker(1, 0);

Thread t1 = new Thread(new IdWorkThread(set, idWorker1));

Thread t2 = new Thread(new IdWorkThread(set, idWorker2));

t1.setDaemon(true);

t2.setDaemon(true);

t1.start();

t2.start();

try {

Thread.sleep(30000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

7,总结

(1)单实例或者单节点组:

经过500W、1000W的单机表测试,自增ID相对UUID来说,自增ID主键性能高于UUID,磁盘存储费用比UUID节省一半的钱。所以在单实例上或者单节点组上,使用自增ID作为首选主键。

(2)分布式架构场景:

20个节点组下的小型规模的分布式场景,为了快速实现部署,可以采用多花存储费用、牺牲部分性能而使用UUID主键快速部署;

20到200个节点组的中等规模的分布式场景,可以采用自增ID+步长的较快速方案。

         200以上节点组的大数据下的分布式场景,可以借鉴类似twitter雪花算法构造的全局自增ID作为主键。

不同数据量下主键类型的选择相关推荐

  1. MySQL 数据表主键设计,选择自增 id 还是 UUID 还是雪花 id?

    在 MySQL 数据表的设计中,官方推荐我们不要使用 UUID 或者其他不连续不重复的 id,而是推荐使用连续自增的主键 id(auto_increment). 随着现在许多项目都涉及到了分布式或者微 ...

  2. 百万数据量下,使用延迟关联优化超大分页

    百万数据量下,使用延迟关联优化超大分页 MySQL 并不是跳过 offset 行,而是取 offset + N 行,然后返回放弃前 offset 行,返回 N 行,那当offset 特别大的时候,效率 ...

  3. 一招教你解决大数据量下的各种报表使用问题

    在我们日常制作报表分析过程中,总会遇到各种问题.比如,报表底层数据日益增多.报表加载超慢,这些情况该怎么解决? 数据库是最常见的能处理大数据的计算方案,而永洪能利用数据库来完成数据计算.但是,有些报表 ...

  4. Mybatis插入数据后获取主键的值

    Mybatis插入数据后获取主键的值 1. 所使用的数据库是支持自增的,且主键是自增的 <!-- 支持自增的数据库且主键是自增的:自动将插入后自增id的值赋值给传入的Employee的id--& ...

  5. php tp5清空数据表并主键,tp5数据库——更新数据

    更新数据 更新数据表中的数据 Db::table('think_user')->where('id', 1)->update(['name' => 'thinkphp']); 如果数 ...

  6. oracle批量插入并且返回自增主键_mybatis + (oracle)实现主键自增 + 插入数据并返回主键...

    一.实现主键自增 在oracle数据库中,主键并没有办法自动增长,无法使用insert对应的useGeneratedKeys和keyProperty属性自动返回增加的主键. 要实现自增需要修改 ID列 ...

  7. 达观数据CTO纪达麒:小标注数据量下自然语言处理实战经验

    自然语言处理在文本信息抽取.自动审校.智能问答.情感分析等场景下都有非常多的实际应用需求,在人工智能领域里有极为广泛的应用场景.然而在实际工程应用中,最经常面临的挑战是我们往往很难有大量高质量的标注语 ...

  8. Controller规范和接口定义,添加一条新数据并返回此数据的ID(主键)

    参考文章: 烂代码之:Controller规范和接口定义 添加一条新数据并返回此数据的ID(主键) 删除数据返回boolean 添加数据后返回Id <insert id="" ...

  9. MySQL:创建数据库,数据表,主键和外键

    目录 前言: 安装MySQL: 打开MySQL: 创建数据库: 查看已建数据库: 查看数据库引擎: 创建数据表: 主键约束: 单字段主键: 多字段联合主键: 外键约束: 前言: MySQL数据库安装了 ...

  10. python mysql批量insert数据、返回id_Python3 操作 MySQL 插入一条数据并返回主键 id的实例...

    Python 中貌似并没有直接返回插入数据 id 的操作(反正我是没找到),但是我们可以变通一下,找到最新插入的数据 #!/usr/bin/env python3 # -*- coding: UTF- ...

最新文章

  1. AVR开发 Arduino方法(附四) 参考文献与网址
  2. 人工智能的人文主义,如何让AI更有爱
  3. 为DataList和GridView内容项添加序号
  4. [渝粤教育] 西南科技大学 单片机原理与应用 在线考试复习资料(2)
  5. vue.js能美化界面吗_vue将单页面改造成多页面应用的方法
  6. [中山市选]杀人游戏 (Tarjan缩点)
  7. 分支和循环结构的应用(习题)
  8. Design-patterns-JS:用JavaScript实现23种设计模式
  9. otsu算法_【车牌识别算法】
  10. 卡函数or1200基于simple-spi的SD卡驱动
  11. office 论文 页码_还在花钱找人排版?这份最全攻略,让你论文一次过!
  12. 考育婴师看什么书?中级育婴师需要备考多久?
  13. 欧几里得算法及其证明
  14. 网站刷关键词_B2B关键词调研:如何精准地定位B端客户?(下)
  15. android tee os,有关OP-TEE - 中文社区论区 - 中文社区 - Arm Community
  16. 英语语法之后缀决定词性
  17. 欠债还钱,天经地义(一)
  18. C++2022NOC之初赛数字规律
  19. win 通过 Distro 安装 linux 子系统
  20. sizeof求二维数组的大小

热门文章

  1. Windows10视频文件服务器启动失败,Win10安全中心服务启动失败的解决方法
  2. Pyspark:NLP(文本分类)
  3. 翻译: 3.线性神经网络 概览 深入神经网络 pytorch
  4. 极客大学产品经理训练营 产品思维和产品意识 作业2
  5. 【易实战】Spring Cloud Greenwich Ribbon:负载均衡的服务调用
  6. 阿玛尼搜索引擎收录_被全网黑的阿玛尼权利,我一个大干皮咋用的挺好?
  7. 主题图标_【主题爱好者】简约全局主题【归途】
  8. 【机器学习系列】MCMC第一讲:蒙特卡罗方法初认识
  9. 估计理论(5):BLUE的定义(6.3)
  10. 为什么说bagging是减少variance,而boosting是减少bias?