【Five-Minute Share】“为什么要选择自增型的主键”
我们在开发的时候经常会听到这样的建议:1. 设计数据库表的时候,要为每个表设置一个主键;2. 主键最好是跟业务无关的; 3. 最好是自增的;
于是,很多新入行的程序猿们把这些前辈们的教条拿来就用,每个表的开头都会有个ID字段,并且在自增那里再打上个“勾勾”。OK,万事大吉,开始Coding。这个习惯有不少人甚至是保持了好多年,却从来没思考过对与不对,更不说为什么了。今天,我们来一起简单地分析一下原因,希望起到抛砖引玉的作用,引起大家进一步深入研究的兴趣。
主键主要作用:数据完整性;让相邻键值的数据紧凑地存放在一起;加快访问速度等。
为什么建议业务无关:避免因业务变更导致应用需要进行各种大量的修改,进而对系统的安全、稳定性进行冲击;
为什么一定自增:其实这才是本次分享里最想提的内容。自增保证了每一条新数据的值都是比当前最大值大的,所以新生成的记录会被写入数据页的末端。而末端的好处就是避免了各种复杂的寻址过程,也降低了索引分裂的成本。【可拓展阅读索引分裂相关内容】
在数据库服务中,一般情况下对每一行数据(准确的说是每一个数据块,实际上数据库从来都不是按行而是按页/数据块读取数据)的修改是从磁盘读到缓存(内存),在缓存中修改完成后又刷回磁盘的过程。(【数据库高速缓存—〉磁盘缓存—〉从磁盘读取】 从左到右成本逐步上升)
如果我们的主键是随机的,且有大有小,如果正好新生成的主键比当前最大值要小,数据库就需要先去高速缓存中查找是否已存在新数据需要写入的数据块,如果没有,则需要去磁盘上将该数据块读回缓存,导致增加了磁盘的随机IO(对于数据库性能来说降低磁盘IO非常重要);而频繁的数据页分裂,也导致数据变得不再紧凑,产生大量碎片。
看到这里,大家应该也可以看到。“自增型主键”其实不是一个结果,而是一个解决问题的方式而已,看到问题的本质,其实就算不用自增型,其他方式也一样可以达到同样的效果,不是吗?
凡事都是有利有弊,关键在于你该怎么去平衡、去取舍。那么自增型的主键又存在什么样的弊端呢?因为新数据都是写在末端,那么在高并发写入的情况下,将会产生“热点块”,对“热点块”的读写产生强烈的资源竞争。所以,同样会引起另外一个方面的性能问题。至于解决方法?其实也没有唯一的标准答案,大家都尝试一下吧(o^^o)
【Five-Minute Share】“为什么要选择自增型的主键”的更多相关文章
- MySql数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述): SELECT table_name name,TABLE_COMMENT value FROM INFORMATION_SCHEMA.TABLES WHERE table ...
- SqlServer数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述) Value ) AS value FROM sysobjects a Where a.xtype = 'U' AND a.name <> 'sysdiagram ...
- Oracle数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述) Select table_Name As Name,Comments As Value From User_Tab_Comments Where table_Type='T ...
- PostgreSql数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述) select a.relname as name , b.description as value from pg_class a ) b on a.oid = b.obj ...
- (转)mysql自增列导致主键重复问题分析
mysql自增列导致主键重复问题分析... 原文:http://www.cnblogs.com/cchust/p/3914935.html 前几天开发童鞋反馈一个利用load data infile ...
- mysql自增列导致主键重复问题分析。。。
前几天开发童鞋反馈一个利用load data infile命令导入数据主键冲突的问题,分析后确定这个问题可能是mysql的一个bug,这里提出来给大家分享下.以免以后有童鞋遇到类似问题百思不得其解,难 ...
- 获取mybatis注解方式新增数据时非自增插入的主键
场景:插入数据的时候,获取不到非自增的主键.原因:对象中没有主键的值,插入后主键才有值. 解决方案:使用 @SelectKey @SelectKey中: statement是要运行的SQL语句,即查询 ...
- mybatis oracle 插入自增记录 获取主键值 写回map参数
网上搜了好多文章照着弄都返回不了主键给map, 实践证明要在传入的map参数里写回插入的主键,要这样写 <selectKey resultType="java.lang.Integer ...
- mybatis+sqlserver中返回非自增主键
首先把实体类贴出来(这里只贴出属性,其它的就是getter和setter方法): public class Around { private String xccd; //对应主键 ...
随机推荐
- kmp板子
kmp 容易理解板子 详情见知乎 算法思想 对模式串求PMT,但实际上nxt数组是PMT向前移动一位 nxt数组含义:记母串为m[],模式串为p[]; m[i]与p[j]比较失配,需要比较m[i]与p ...
- Python画三维图-----插值平滑数据
一.二维的插值方法: 原始数据(x,y) 先对横坐标x进行扩充数据量,采用linspace.[如下面例子,由7个值扩充到300个] 采用scipy.interpolate中的spline来对纵坐标数据 ...
- 【剑指Offer】60、把二叉树打印成多行
题目描述: 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 解题思路: 本题可类比第22题:从上往下打印二叉树,这两道题实际上是一回事,只不过这里我们多了一个分行打印 ...
- 【剑指Offer】32、把数组排成最小的数
题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. ...
- C#第三节课(2)
运算符 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.T ...
- 值得收藏--GitHub Top 20 开源项目
参考链接:https://github.com/Aufree/trip-to-iOS/blob/master/Top-100.md 项目名称 项目 ...
- node源码详解(三)
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource3 本博客同步在https://cnodejs.o ...
- noip模板复习
自己敲模板还是有很多容易错的地方 写在注释里面了 LCA #include<bits/stdc++.h> #define REP(i, a, b) for(register int i = ...
- 11、mybatis的映射xml中参数类型的别名
在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型.需要resultType指定输出结果的映射类型. 如果在指定类型时输入类型全 ...
- chrome 插件开发2
登录 | 注册 基础文档 综述 调试 Manifest 文件 代码例子 模式匹配 分类索引 改变浏览器外观 Browser Actions 右键菜单 桌面通知 Omnibox 选项页 覆写特定页 ...