在Mysql表设计中,通常会使用一个与业务无关的自增列做为主键。
这是因为Mysql默认使用B-Tree索引,你可以简单理解为“排好序的快速查找结构”。
如下是一个B-Tree的结构图,2层B+树,每个页面的扇出为4;并有1到6五条记录;上层记录保存每个页面的最小值;每个页面通过双向链表链接起来的;
当你插入记录7时,就会发生页面分裂:

如上可见分裂产生了记录移动,但是优化后的分裂操作无需记录移动:

在InnoDB的实现中,为每个索引页面维护了一个上次插入的位置,以及上次的插入是递增/递减的标识。根据这些信息,InnoDB能够判断出新插入到页面中的记录,是否仍旧满足递增/递减的约束,若满足约束,则采用优化后的分裂策略;
所以建议使用一列顺序递增的 ID 来作为主键,但不必是数据库的autoincrement字段,只要满足顺序增加即可 。很多大型应用会有顺序递增的ID生成器。
测试如下:


  1. CREATE TABLE `table1` (
  2. `id` int(10) NOT NULL AUTO_INCREMENT,
  3. `text` varchar(255) NOT NULL,
  4. PRIMARY KEY (`id`)
  5. ) ENGINE=InnoDB AUTO_INCREMENT=200001 DEFAULT CHARSET=utf8
  6. CREATE TABLE `table2` (
  7. `id` int(10) NOT NULL,
  8. `text` varchar(255) NOT NULL,
  9. KEY `id` (`id`)
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8

脚本如下:


  1. $link = mysql_connect('127.0.0.1', 'root', 'mckee');
  2. mysql_select_db('test', $link);
  3. $count = 200000;
  4. $table1_data = range(1, $count);
  5. $text = 'just test!just test!just test!just test!just test!';
  6. $time1 = get_time();
  7. foreach ($table1_data as $row) {
  8. $id = rand(1,100000000);
  9. mysql_query("insert into table1(text) values ('{$text}')");
  10. }
  11. $time2 = get_time();
  12. foreach ($table1_data as $row) {
  13. $id = rand(1,100000000);
  14. mysql_query("insert into table2(id, text) values ({$id}, '{$text}')");
  15. }
  16. $time3 = get_time();
  17. echo 'tabe1 insert execute time:' . ($time2 - $time1) . PHP_EOL;
  18. echo 'tabe2 insert execute time:' . ($time3 - $time2) . PHP_EOL;
  19. function get_time()
  20. {
  21. list( $usec , $sec ) = explode ( " " , microtime ());
  22. return ((float) $usec + (float) $sec );
  23. }

InnoDB为什么要使用auto_Increment的更多相关文章

  1. Mysql引擎中MyISAM和InnoDB的区别有哪些?

    简单的概括一下 InnoDB:支持事务处理等不加锁读取支持外键支持行锁不支持FULLTEXT类型的索引不保存表的具体行数,扫描表来计算有多少行DELETE 表时,是一行一行的删除InnoDB 把数据和 ...

  2. MySQL中MyISAM与InnoDB区别

    原文:https://blog.csdn.net/frycn/article/details/70158313?utm_source=copy InnoDB:支持事务处理等不加锁读取支持外键支持行锁不 ...

  3. MySQL中MyISAM与InnoDB区别及选择(转)

    InnoDB: 支持事务处理等 不加锁读取 支持外键 支持行锁 不支持FULLTEXT类型的索引 不保存表的具体行数,扫描表来计算有多少行 DELETE 表时,是一行一行的删除 InnoDB 把数据和 ...

  4. MySQL中MyISAM与InnoDB区别及选择

    InnoDB:支持事务处理等不加锁读取支持外键支持行锁不支持FULLTEXT类型的索引不保存表的具体行数,扫描表来计算有多少行DELETE 表时,是一行一行的删除InnoDB 把数据和索引存放在表空间 ...

  5. MySQL使用AUTO_INCREMENT列的表注意事项之update自增列篇

    1)对于MyISAM表,如果用UPDATE更新自增列,如果列值与已有的值重复,则会出错:如果大于已有的最大值,则会自动更新表的AUTO_INCREMENT,操作是安全的. (2)对于innodb表,u ...

  6. MyISAM和InnoDB区别 及选择

    MySQL默认采用的是MyISAM. MyISAM不支持事务,而InnoDB支持.InnoDB的AUTOCOMMIT默认是打开的,即每条SQL语句会默认被封装成一个事务,自动提交,这样会影响速度,所以 ...

  7. MySQL中MyISAM与InnoDB区别及选择,mysql添加外键

    InnoDB:支持事务处理等不加锁读取支持外键支持行锁不支持FULLTEXT类型的索引不保存表的具体行数,扫描表来计算有多少行DELETE 表时,是一行一行的删除InnoDB 把数据和索引存放在表空间 ...

  8. mysql innodb myisam 比较

    InnoDB: 支持事务处理等 不加锁读取 支持外键 支持行锁 不支持FULLTEXT类型的索引 不保存表的具体行数,扫描表来计算有多少行 DELETE 表时,是一行一行的删除 InnoDB 把数据和 ...

  9. MySql中存储引擎MyISAM与InnoDB区别于选择

    InnoDB: 支持事务处理等 不加锁读取 支持外键 支持行锁 不支持FULLTEXT类型的索引 不保存表的具体行数,扫描表来计算有多少行 DELETE 表时,是一行一行的删除 InnoDB 把数据和 ...

随机推荐

  1. HDU 3038 How Many Answers Are Wrong(带权并查集)

    传送门 Description TT and FF are ... friends. Uh... very very good friends -________-b FF is a bad boy, ...

  2. c 开源代码

    阅读优秀代码是提高开发人员修为的一种捷径……1. WebbenchWebbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在 ...

  3. ::before/:before和::after/:after的使用

    ::before/:before和::after/:after的使用 之前总是可以看到::before :before ::after :after,但是没有使用过,今天查了些资料,终于知道了他们的关 ...

  4. Install latest R for ubuntu

    ### delete old version rm -rf /usr/local/lib/R /usr/lib/R ~/**/R sudo apt-get autoremove rstudio sud ...

  5. JS-制作可伸缩的水平菜单栏

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...

  6. VGA 视频输出

    VGA Video Output by Nathan Ickes Introduction VGA is a high-resolution video standard used mostly fo ...

  7. PHP中常用的字符串格式化函数总结

    注意:在PHP中提供的字符串函数处理的字符串,大部分都不是在原字符串上修改,而是返回一个格式化后的新字符串. 一.取出空格和字符串填补函数 空格也是一个有效的字符,在字符串中也会占据一个位置.用户在表 ...

  8. SQL Server编程(02)自定义函数

    在编程过程中,我们通常把特定的功能语句块封装称函数,方便代码的重用.我们可以在SQL Server中自定义函数,根据函数返回值的区别,我们自定义的函数分两种:标量值函数和表值函数. 自定义函数的优点: ...

  9. C#获取C++中修改过的float数组(指针),dll

    C++中 struct rankPoint{ float sim; }; ]){ ; i < ; i++) prank[i].sim = ; ; i < ; i++) prank[i].s ...

  10. nodejs fs module

    fs.watchFile(filename[, options], listener)# Added in: v0.1.31 filename <String> | <Buffer& ...