数据库的唯一标示符(ID)的选择 推荐 原创 一个叫大姚的工程师 2014-10-24 19:40:31 ©著作权 文章标签 数据库 id 逻辑主键 业务主键 文章分类 软件研发 ©著作权归作者所有:来自51CTO博客作者一个叫大姚的工程师的原创作品,请联系作者获取转载授权,否则将追究法律责任 背景:数年的工作中,已经设计了很多系统或产品的数据库,有单机的、有局域网环境下的、也有互联网环境下的,对于不同的环境,设计考虑都有所不同。即使对于相同的环境,也会因为业务或者数据量的不同而有不同的设计。近期,又要设计一款互联网产品的数据库(MySQL服务)。经过之前的积累,在表的ID设计这个环节就进行了大量的分析、比较、学习,对ID的设计也有了更系统和深刻的认知,把自己学习实践到的知识总结下来,分享给大家。主键id的选择对于关系数据库来说,设计每个表的第一步都会确定其主键,主键就是ID。在“常识”之中,int型的自增id,字符串类型的uuid,其他与业务相关的唯一键…都是我们作为主键的选择。那么是不是说在一张表中只要能保证值唯一的属性列都可以做为主键或者更合适做主键呢?那我们首先清晰几个概念:逻辑主键(代理主键):在数据库表中采用一个与当前表中业务逻辑信息无关的字段作为其主键,或称为“伪主键”;业务主键(自然主键):在数据库表中把具有业务逻辑含义的字段作为主键;举一个很常见的例子:一张用户信息表,列属性有id、用户名、手机号…,其中用户名和手机号(作为登录账号二者都是唯一的)。其中id便可作为逻辑主键,用户名和手机号都可以作为业务主键。那我是不是可以随便选一个,甚至我选择了业务主键都可以不要逻辑主键?那么我们首先来看看逻辑主键和业务主键之间纷纷烈烈的观点分歧:支持逻辑主键表通过主键来保证每条记录的唯一性,表的主键应当不具有任何业务含义,因为任何有业务含义的列都有改变的可能性。关系数据库学的最重要的一个理论就是:不要给关键字赋予任何业务意义。假如关键字具有了业务意义,当用户决定改变业务含义,也许他们想要为关键字增加几位数字或把数字改为字母,那么就必须修改相关的关键字。一个表中的主关键字有可能被其他表作为外键。就算是一个简单的改变,譬如在客户号码上增加一位数字,也可能会造成极大的维护上的开销。为了使表的主键不具有任何业务含义,一种解决方法是使用代理主键,例如为表定义一个不具有任何业务含义的ID字段(也可以叫其他的名字),专门作为表的主键。——孙卫琴《精通Hibernate:Java对象持久化技术详解》P8使用逻辑主键的主要原因是,业务主键一旦改变则系统中关联该主键的部分的修改将会是不可避免的,并且引用越多改动越大。而使用逻辑主键则只需要修改相应的业务主键相关的业务逻辑即可,减少了因为业务主键相关改变对系统的影响范围。业务逻辑的改变是不可避免的,因为“永远不变的是变化”,没有任何一个公司是一成不变的,没有任何一个业务是永远不变的。最典型的例子就是***升位和驾驶执照号换用***号的业务变更。而且现实中也确实出现了***号码重复的情况,这样如果用***号码作为主键也带来了难以处理的情况。当然应对改变,可以有很多解决方案,方案之一是做一新系统与时俱进,这对软件公司来说确实是件好事。使用逻辑主键的另外一个原因是,业务主键过大,不利于传输、处理和存储。我认为一般如果业务主键超过8字节就应该考虑使用逻辑主键了,因为int是4字节的,bigint是8字节的,而业务主键一般是字符串,同样是 8 字节的 bigint 和 8 字节的字符串在传输和处理上自然是 bigint 效率更高一些。想象一下 id 为”12345678” 和 id为12345678 的汇编码的不同就知道了。当然逻辑主键不一定是 int 或者 bigint ,而业务主键也不一定是字符串也可以是 int 或 datetime 等类型,同时传输的也不一定就是主键,这个就要具体分析了,但是原理类似,这里只是讨论通常情况。同时如果其他表需要引用该主键的话,也需要存储该主键,那么这个存储空间的开销也是不一样的。而且这些表的这个引用字段通常就是外键,或者通常也会建索引方便查找,这样也会造成存储空间的开销的不同,这也是需要具体分析的。使用逻辑主键的再一个原因是,使用 int 或者 bigint 作为外键进行联接查询,性能会比以字符串作为外键进行联接查询快。原理和上面的类似,这里不再重复。使用逻辑主键的再一个原因是,存在用户或维护人员误录入数据到业务主键中的问题。例如错把 RMB 录入为 RXB ,相关的引用都是引用了错误的数据,一旦需要修改则非常麻烦。如果使用逻辑主键则问题很好解决,如果使用业务主键则会影响到其他表的外键数据,当然也可以通过级联更新方式解决,但是不是所有都能级联得了的。——SwitchBlade的总结支持业务主键如果你的表中包含一列能确保唯一、非空以及能够用来定位一条记录,就别仅仅因为传统而觉得有必要再加上一个伪主键。——Bill Karwin 《SQL反模式》 p41使用业务主键的主要原因是,增加逻辑主键就是增加了一个业务无关的字段,而用户通常都是对于业务相关的字段进行查找(比如员工的工号,书本的 ISBN No. ),这样我们除了为逻辑主键加索引,还必须为这些业务字段加索引,这样数据库的性能就会下降,而且也增加了存储空间的开销。所以对于业务上确实不常改变的基础数据而言,使用业务主键不失是一个比较好的选择。另一方面,对于基础数据而言,一般的增、删、改都比较少,所以这部分的开销也不会太多,而如果这时候对于业务逻辑的改变有担忧的话,也是可以考虑使用逻辑主键的,这就需要具体问题具体分析了。使用业务主键的另外一个原因是,对于用户操作而言,都是通过业务字段进行的,所以在这些情况下,如果使用逻辑主键的话,必须要多做一次映射转换的动作。我认为这种担心是多余的,直接使用业务主键查询就能得到结果,根本不用管逻辑主键,除非业务主键本身就不唯一。另外,如果在设计的时候就考虑使用逻辑主键的话,编码的时候也是会以主键为主进行处理的,在系统内部传输、处理和存储都是相同的主键,不存在转换问题。除非现有系统是使用业务主键,要把现有系统改成使用逻辑主键,这种情况才会存在转换问题。暂时没有想到还有什么场景是存在这样的转换的。使用业务主键的再一个原因是,对于银行系统而言安全性比性能更加重要,这时候就会考虑使用业务主键,既可以作为主键也可以作为冗余数据,避免因为使用逻辑主键带来的关联丢失问题。如果由于某种原因导致主表和子表关联关系丢失的话,银行可是会面临无法挽回的损失的。为了杜绝这种情况的发生,业务主键需要在重要的表中有冗余存在,这种情况最好的处理方式就是直接使用业务主键了。例如***号、存折号、卡号等。所以通常银行系统都要求使用业务主键,这个需求并不是出于性能的考虑而是出于安全性的考虑。——SwitchBlade的总结所以说明逻辑主键和业务主键的选择并不是拍脑瓜的结果,而是根据不同的应用场景、不同的需求决策的结果。如果我们使用整数类型的自增id作为主键又会面临什么问题呢?对于数据量非常大的表后期往往会涉及到水平分表的需求,这时这个自增主键会成为阻碍。(其实关于这种情况也会有解决方案,请参见文章《又拍网架构中的分库设计》ID数据类型的选择我们再换一个角度考虑主键的选择:数据类型。整数类型:整数类型往往是id列最好的选择,因为效率最高并且可以使用数据库的自增主键。字符串类型字符串类型相比整数类型肯定更消耗空间,也会比整数类型操作慢。我主要使用的是Mysql,关于这个话题的解释建议看《高性能MySQL》第三版 P125。我采用的方案(MySQL):使用自增id作为主键,以此来应对插入效率问题;采用uuid做逻辑id,拥有了逻辑主键的诸多好处,而且可以用来应对之后的水平分表。 赞 收藏 评论 分享 举报 上一篇:我的网络编程之旅——P2P相关话题 下一篇:我看产品 提问和评论都可以,用心的回复会被更多人看到 评论 发布评论 全部评论 () 最热 最新 相关文章 什么是数据库表的 schema 在详细介绍数据库领域的 schema 之前,让我们首先理解数据库是如何在各种应用程序中发挥核心作用的。数据库不仅仅是存储数据的容器,它还管理着数据的结构、存储方式和数据之间的关系,确保数据的完整性、一致性和安全性。在这个基础上,schema 的概念自然而然地成为了数据库设计和实现的关键要素。Schema 在数据库领域中,指的是数据库中数据的组织和结构的定义。它包括了数据库中所有表的定义、字段的名 数据库 数据 字段 6 修改表 -- MySQL数据库 实例:修改表 emp 的 ename 字段,将 varchar(10) 改为 将 varchar(20)mysql> alter table emp modify ename varchar(20);实例:表 emp 新增字段 age,类型为 intmysql> alter table emp add age int;... ... mysql 字段 表名 SQL数据库入门07:自定义数据类型与用户定义函数(标量值、内嵌表值、多语句表值函数等) 本文介绍基于Microsoft SQL Server软件,实现数据库用户自定义数据类型的创建、使用与删除,以及标量值、内嵌表值、多语句表值函数等用户定义函数的创建、使用、删除方法~ SQL 数据库 SQL Server 自定义数据类型 用户定义函数 mysql数据库表修改id自增起始值 # 如何修改MySQL数据库表的id自增起始值## 引言在使用MySQL数据库时,我们经常需要创建表并定义自增主键。默认情况下,MySQL会为每个自增主键字段设置一个起始值为1的自增序列。但有时我们可能需要修改自增起始值,这篇文章将教你如何实现这一操作。## 流程概述修改MySQL数据库表的id自增起始值可以分为以下几个步骤:1. 创建一个新的表,将原表的数据导入到新表中。2. 自增 MySQL 重命名 用MySQL创建数据库和数据库表 1、使用SHOW语句找出在服务器上当前存在什么数据库 (0.00 sec)2、创建一个数据库abccs mysql> C mysql 数据库 bc Android数据库用什么 # Android数据库选择与实现方法## 一、流程表格| 步骤 | 描述 || --- | --- || 1 | 选择数据库类型 || 2 | 创建数据库帮助类 || 3 | 定义数据表结构 || 4 | 实现数据库的增删改查操作 |## 二、具体步骤及代码示例### 1. 选择数据库类型在Android开发中,常用的数据库有SQLite、Room等,我们这里选择使用 SQL 数据库 帮助类 java创建数据库表id自增 # Java创建数据库表id自增在Java开发中,我们经常需要与数据库进行交互,其中一个常见的需求是创建数据库表,并为表中的id字段实现自增功能。本文将介绍如何使用Java创建数据库表,并使用自增字段来管理表中的id。## 使用JDBC连接数据库要使用Java创建数据库表,首先需要建立与数据库的连接。Java提供了JDBC(Java Database Connectivity)API来 sql java 创建数据库 hadoop 用什么数据库 ## Hadoop与数据库的关系在大数据分析领域,Hadoop已经成为了一种非常流行的工具,它提供了一种分布式的计算框架,能够方便地处理大规模的数据。然而,当我们需要对这些数据进行持久化存储时,就需要借助数据库来进行管理。Hadoop并不是一个数据库,它本身并不提供数据的存储和管理功能。然而,Hadoop可以与各种类型的数据库集成,以便更好地进行数据处理和查询。根据具体的需求和场景,我们可 数据库 Hadoop Text PYTHON 查询数据库ID数值返回值 python 查询数据库表 python操作oracle数据库-查询DB API 2.0 和 cx_Oracle 介绍Python 数据库 API 规范 v2.0 是集体努力的成果,用于统一不同数据库系统的访问模型。拥有一组相对较少的方法和属性,在更换数据库供应商时就易于学习并保持一致。它不以任何方式将数据库对象映射到 Python 结构中。用户仍然需要手工编写 SQL。在更换到另一数据库后,此 SQL 可能需要重新编写。尽 PYTHON 查询数据库ID数值返回值 数据库 Python SQL Android数据库用什么 android数据库用什么不同 Android系统集成了一个轻量级的数据库:SQLite,所以Android对数据库的支持很好,每个应用都可以方便的使用它。SQLite作为一个嵌入式的数据库引擎,专门适用于资源有限的设备上适量数据存取,现在的主流移动设备像Android、iPhone等都使用SQLite作为复杂数据的存储引擎,并且它是以手机内存为储存的。 那么,实际开发项目中有大量数据需要读写,并且需要面临大量用户的并发储 Android数据库用什么 android SQLite XML Network 数据库用python 数据库用SQL语句创建表 目录创建和使用数据表创建数据表通过SQL语句创建数据表定义数据表的约束1. 检查约束(CHECK)2. 非空约束(NOT NULL)3. 唯一约束(UNIQUE)4. 主键约束(PRIMARY KEY)5. 外键约束(FOREIGN KEY) 创建和使用数据表数据表示数据库中最重要的对象之一。表是存储数据的场所,是数据的集合,是用来存储数据和操作数据的逻辑结构。创建数据表通过SQL语句创建数据表 数据库用python sql 数据库 主键 字段 Android 用什么数据库 安卓程序用什么数据库 数据库即存储数据的仓库,不管是在PC端还是移动手机客户端都非常重要,应用也非常广泛,如手机中的通讯录应用、短消息应用、日历,邮箱应用等都基于本地数据库存储数据的,而Android手机中使用的是Sqlite数据库。 &nbs Android 用什么数据库 SQL 数据库 sql MES数据库表架构 mes一般用什么数据库 1 MES(Manufacturing Execution System)是以实时数据库(RTDB:Real-Time Database)为核心,以经济运行和提高炼化企业整体效益为目的,采用先进的计算机控制技术和适用的专业计算方法,实现整个企业范围内的信息集成与共享。 2 MES与实时数据库 MES是连接企业管理信息系统MIS(Management Information MES数据库表架构 数据库 存储 system 语言 es的id可以用数据库id吗 es作为数据库使用 文章概要前面随便说一点 Elasticsearch ,简称es,主要运用于全文搜索、数据分析, 底层使用开源库Lucene,拥有丰富的REST API,开箱即用。分布式的数据存储、倒排索引等设计,使其可以快速存储、搜索、分析海量数据。典型的使用方和应用场景,如github,StackOverflow,elasticsearch+logstash+kibana 一体化的日志分析。 下面主要从我们如何 es的id可以用数据库id吗 数据 字段 数据库 mysql 订单商品表用什么引擎 订单表数据库 今天,我们要完成订单数据库的设计与创建,这样才能够记录便利店与顾客的交易信息一、定义商品数据库表 商品数据数据库表的内容包括:商品名、商品编号、商品描述 根据之前数据库内容所学,我们需要在common中的models.py中定义数据库表:class Commodity(models.Model): # 商品名 name = models.CharField(max_length=2 mysql 订单商品表用什么引擎 数据库 mysql python django 数据仓库建议用什么数据库 数据仓库 用什么数据库 数据库是面向事务的,数据仓库是面向主题的。数据库一般存储在线交易数据,数据仓库一般存储历史数据。数据库设计是尽量避免冗余,一般采用范式规则设计,数据仓库设计有意引入冗余,采用反范式设计。数据库是为获取数据设计,数据仓库是为分析数据设计,数据仓库两个基本的元素是维表和事实表。数据库通常更关注业务交易处理(OLTP),数据仓库更关注数据分析层面(OLAP)。数据库比较流行的有Oracle、MYSQL、 数据仓库建议用什么数据库 数据仓库 数据 数据库 数据库中新建表AUTO_INCREMENT是什么用 新建数据库新建表 使用界面操作进行数据操作: 1.只要电脑有SQL服务,电脑就可以跑SQL软件,对象资源管理软件只是一个自带的管理界面。只要有服务就可以被其他电脑连接,有这个界面就可以更好的显示与开发:下面这个界面与sever没有关系创建:右键数据库,添加新的数据库: 保存路径: 建完后:分离:如果将这些文件移动到其他地方:需要首先数据库右键分离附加:再次添加数据表:附加直接添加文件:生成脚本:(架构,数据)不希望 数据库 数据 主键 Python数据库主键自增id python数据库创建表 首先需要安装mysql,安装时注意自己填写的端口号,比如我没有用常用的3306,而是用的3366,还要记住自己mysql的密码打开Navicat for MySQL,找到左上角的连接选项,填写相关内容,连接名可以任意,习惯写为自己名字的简写或者本机的ip地址,端口号需要与安装MySQL时填写的端口号相同,密码也要与MySQL中的密码保持一致点击确定之后,双击连接名然后会显示已有的数据库,由于我之前 数据库 Python mysql MySQL sql server 数据库表 id重置 sql server 数据库改名 把Old数据库改为New数据库打开“企业管理器”找到 Old数据库--》右键--》所有任务--》分离数据库然后到C:\Program Files\Microsoft SQL Server\MSSQL\Data下找到Old_Data.mdf和 Old_log.ldf把Old_Data换成你想要的名字例如New.mdf、New.ldf然后到企业管理器,找到 数据库 --》右键--》所有任务--》附加数 数据库 sqlserver sql server database microsoft 用什么数据库做数据仓库 一般用什么数据库 数据库是计算机时代有效储存数据的手段,那么现在常用的数据库有哪些呢?在现在的应用当中,最常见的数据库模型是关系型数据库和非关系型数据库这两种数据库类型。 一、关系型数据库的简要介绍 关系型数据库模型是把复杂的数据结构归结为简单的二元关系(即二维表格形式)。在关系型数据库中,对数据的操作几乎全部建立在一个或多个关系表格上,通过对这些关联的表格分类、合并、连接或选取等运算来实现数据库的管理。其实, 用什么数据库做数据仓库 大数据 数据库 mysql 服务器