引言
关系数据模型以行和列的表格形式组织数据,在数据库管理工具中占主导地位。今天还有其他数据模型,包括NoSQL和NewSQL,但是关系数据库管理系统(RDBMS)仍然占主导地位用于存储和管理全球数据。
本文比较了三种实现最广泛的开源RDBMS:SQLite、MySQL和PostgreSQL。具体来说,本章将探讨每种RDBMS使用的数据类型、它们的优缺点,以及它们最适合优化的情况。
数据库管理系统简介
数据库是对信息或数据进行逻辑建模的集群。另一方面,数据库管理系统 (DBMS)是与数据库交互的计算机程序。DBMS允许你控制对数据库的访问、写入数据、执行查询以及执行与数据库管理相关的任何其他任务。
虽然数据库管理系统通常被称为“数据库”,但这两个术语是不可互换的。数据库可以是任何数据集合,而不仅仅是存储在计算机上的数据。相比之下,DBMS特指允许您与数据库交互的软件。
所有数据库管理系统都有一个底层模型,该模型对数据的存储和访问方式进行结构化。关系数据库管理系统是一种采用关系数据模型的DBMS。在这种关系模型中,数据被组织成表。表,在RDBMS的上下文中,更正式的叫法是关系(relations)。关系是一组元组(tuples) 的集合,它们是表中的行,每个元组共享一组属性(attributes),这些属性是表中的列:
大多数关系型数据库使用结构化查询语言 (SQL)来管理和查询数据。然而,许多关系数据库使用自己的SQL方言,这可能有一定的限制或扩展。这些扩展通常包含额外的特性,允许用户执行比标准SQL更复杂的操作。
注意: 术语“标准SQL”在本指南中出现多次。SQL标准由美国国家标准协会(ANSI)、国际标准化组织(ISO)和国际电工委员会(IEC)共同维护。当本文提到“标准SQL”或“SQL标准”时,它指的是这些机构发布的SQL标准的当前版本。
需要注意的是,完整的SQL标准既庞大又复杂:完整的核心SQL:2011要求179个功能。正因为如此,大多数RDBMS并不支持整个标准,尽管有些RDBMS确实比其他RDBMS更接近于完全遵从标准。
数据类型和约束
每一列都有一个数据类型,它规定了该列中允许哪些类型的项。不同的RDBMS实现不同的数据类型,这些类型并不总是可以直接互换。一些常见的数据类型包括日期、字符串、整数和布尔值。
在数据库中存储整数比在表中存储数字要微妙得多。数值数据类型可以是有符号(signed),这意味着它们可以表示正数和负数,也可以是无符号(unsigned),这意味着它们只能表示正数。例如,MySQL的tinyint
数据类型可以保存8位数据,相当于256个可能的值。这个数据类型的有符号范围是-128 ~ 127,无符号范围是0 ~ 255。
能够控制哪些数据可以进入数据库是很重要的。有时,数据库管理员会对表施加约束(constraint),以限制可以输入的值。一个约束通常应用于一个特定的列,但一些约束也可以应用于整个表。下面是一些SQL中常用的约束:
UNIQUE
:将此约束应用于列,确保该列中没有两个元素是相同的。NOT NULL
:这个约束确保列不包含任何NULL
元素。PRIMARY KEY
:UNIQUE
和NOT NULL
的组合,PRIMARY KEY
约束确保列中没有NULL
条目,并且每个条目都是不同的。FOREIGN KEY
:FOREIGN KEY
是一张表中的一列,指向另一张表的PRIMARY KEY
。此约束用于将两个表链接在一起。FOREIGN KEY
列的条目必须已经存在于父PRIMARY KEY
列中,这样写进程才能成功。CHECK
:这个约束限制了列可以输入的值的范围。例如,如果这一列是手机号码,则可以在邮政编码列上添加一个CHECK
约束,使条目只允许在13位数。
现在我们已经大体上介绍了关系数据库管理系统,让我们转到本文将介绍的三个开源关系数据库中的第一个:SQLite。
SQLite
SQLite是一个自包含的、基于文件的、完全开源的RDBMS,以其可移植性、可靠性和即使在低内存环境中也具有强大的性能而闻名。其交易符合ACID标准,即使在系统崩溃或经历停电的情况下也是如此。
SQLite项目的网站将其描述为无服务器
数据库。大多数关系型数据库引擎都实现为服务器进程,程序通过中继请求的进程间通信与主机服务器进行通信。相比之下,SQLite允许任何访问数据库的进程直接读写数据库磁盘文件。这简化了SQLite的设置过程,因为它消除了任何配置服务器进程的需要。同样,使用SQLite数据库的程序也不需要配置:它们只需要访问磁盘。
SQLite是免费开源软件,使用它不需要特殊的许可证。然而,该项目确实提供了几个扩展-每个都需要一次性付费-以帮助压缩和加密。此外,该项目还提供各种商业支持包,每个包都需要支付年费。
SQLite支持的数据类型
SQLite允许多种数据类型,数据类型如下:
数据类型 | 说明 |
---|---|
null | 包括任何NULL 值 |
integer | 有符号整数,存储在1、2、3、4、6或8个字节中,具体取决于值的大小。 |
real | 真实的或浮点值,存储为8字节浮点数。 |
text | 使用数据库编码存储的文本字符串,可以是UTF-8、UTF-16 BE或UTF-16 LE。 |
blob | 任何数据blob,每个blob完全按照输入的方式存储。 |
在SQLite的上下文中,术语“存储类”和“数据类型”是可以互换的。如果您想了解有关SQLite的数据类型和SQLite类型关联的更多信息,请查看SQLite的官方文档。 |
SQLite的优点
- 占用空间小:SQLite库是非常轻量级的。尽管它使用的空间因安装它的系统而异,但它可以占用不到600KiB的空间。此外,它是完全自包含的,这意味着你不需要在系统上安装任何外部依赖即可使SQLite工作。
- 用户友好:SQLite有时被描述为“零配置”数据库,可以开箱即用。SQLite不作为服务器进程运行,这意味着它永远不需要停止、启动或重启,也不带任何需要管理的配置文件。这些特性有助于简化从安装SQLite到将其与应用程序集成的过程。
- 可移植性:不像其他数据库管理系统通常将数据存储为大量独立文件,整个SQLite数据库存储在单个文件中。该文件可以位于目录层次结构中的任何位置,并可以通过可移动媒体或文件传输协议共享。
SQLite的缺点
- 有限的并发性:尽管多个进程可以同时访问和查询SQLite数据库,但在任何给定的时间内,只有一个进程可以对数据库进行更改。这意味着虽然SQLite比大多数其他嵌入式数据库管理系统支持更大的并发性,但它不能像MySQL或PostgreSQL这样的客户端/服务器RDBMS那样支持那么多。
- 无用户管理:数据库系统通常支持用户,或者通过预定义的对数据库和表的访问权限来管理连接。因为SQLite直接读写普通磁盘文件,所以唯一适用的访问权限是底层操作系统的典型访问权限。这使得SQLite对于需要多个具有特殊访问权限的用户的应用程序来说是一个糟糕的选择。
- 安全性:在某些情况下,使用服务器的数据库引擎可以提供比无服务器数据库(如SQLite)更好的保护,避免客户端应用程序中的bug。例如,客户端中的游离指针不会破坏服务器上的内存。另外,由于服务器是单一持久进程,因此客户机-服务器数据库可以比无服务器数据库更精确地控制数据访问。这允许更细粒度的锁和更好的并发。
什么时候可以用SQLite?
- 嵌入式应用程序:对于需要可移植性且不需要未来扩展的应用程序,SQLite是一个很好的数据库选择。例如单用户本地应用程序、移动应用程序或游戏。
- 单机程序:在应用程序需要直接读写文件到磁盘的情况下,使用SQLite可以获得SQL带来的额外功能和简单性。
- 测试:对于许多应用来说,使用使用额外服务器进程的DBMS来测试它们的功能可能是多余的。SQLite具有内存模式,可以用于快速运行测试,而无需实际数据库操作的开销,这使它成为测试的理想选择。
什么时候不能使用SQLite?
- 处理大量数据:只要磁盘驱动器和文件系统也支持数据库的大小要求,SQLite在技术上可以支持最大140TB的数据库。然而,SQLite网站建议任何接近1TB的数据库都应该放在一个集中式的客户机-服务器数据库中,因为这种大小或更大的SQLite数据库将很难管理。
- 高写容量:SQLite在任何给定的时间只允许一个写操作发生,这极大地限制了它的吞吐量。如果您的应用程序需要大量写操作或多个并发写入器,那么SQLite可能无法满足您的需求。
- 需要网络访问:因为SQLite是一个无服务器数据库,它不提供对其数据的直接网络访问。这种访问内置在应用程序中。如果SQLite中的数据位于与应用程序不同的机器上,它将需要一个高带宽的引擎到磁盘的网络连接。这是一种昂贵且低效的解决方案,在这种情况下,客户端-服务器DBMS可能是更好的选择。
MySQL数据库
根据DB-Engines排名,从2012年开始跟踪数据库流行程度以来,MySQL一直是最受欢迎的开源RDBMS。它是一个功能丰富的产品,为世界上许多最大的网站和应用程序提供支持,包括阿里巴巴、腾讯、Facebook、Netflix和Spotify。开始使用MySQL是相对简单的,这在很大程度上要感谢它的详尽的文档和大型的开发者社区,以及丰富的MySQL相关在线资源。
MySQL的设计追求的是速度和可靠性,但代价是完全遵循标准SQL。MySQL开发人员不断地朝着遵循标准SQL的方向努力,但它仍然落后于其他SQL实现。然而,它确实提供了各种SQL模式和扩展,使其更接近合规性。
与使用SQLite的应用程序不同,使用MySQL数据库的应用程序通过一个单独的守护进程访问它。因为服务器进程位于数据库和其他应用程序之间,所以它可以更好地控制谁有权访问数据库。
MySQL激发了大量的第三方应用程序、工具和集成库,这些应用程序、工具和库扩展了MySQL的功能,使其更易于使用。这些更广泛使用的第三方工具有phpMyAdmin, DBeaver和HeidiSQL。
MySQL支持的数据类型
MySQL的数据类型可以分为三类:数值类型、日期和时间类型以及字符串类型。
数值类型:
数据类型 | 说明 |
---|---|
tinyint | 非常小的整数。这个数值类型的有符号范围是-128到127,而无符号范围是0到255。 |
smallint | 小整数。此数值类型的有符号范围为-32768到32767,而无符号范围为0到65535。 |
mediumint | 中等大小的整数。此数值数据类型的有符号范围为-8388608到8388607,而无符号范围为0到16777215。 |
int 、integer | 正常大小的整数。此数字数据类型的有符号范围是-2147483648到2147483647,而无符号范围是0到4294967295。 |
bigint | 大整数。此数字数据类型的有符号范围是-9223372036854775808到9223372036854775807,而无符号范围是0到18446744073709551615。 |
float | 小(单精度)浮点数。 |
double 、double precision 、real | 正常大小(双精度)浮点数。 |
dec 、decimal 、fixed 、numeric | 一个压缩的定点数。此数据类型的条目的显示长度在创建列时定义,并且每个条目都遵循该长度。 |
bool 、boolean | 布尔值是一种只有两个可能值的数据类型,通常是 true 或 false 。 |
bit | 一种位值类型,您可以为其指定每个值的位数,从1到64。 |
日期和时间类型:
数据类型 | 说明 |
---|---|
date | 日期,表示为 YYYY-MM-DD 。 |
datetime | 显示日期和时间的时间戳,显示为 YYYY-MM-DD HH:MM:SS 。 |
timestamp | 时间戳,表示自Unix纪元(1970年1月1日00:00:00)以来的时间量。 |
time | 一天中的时间,显示为 HH:MM:SS 。 |
year | 以2位或4位数格式表示的年份,默认为4位数。 |
字符串类型:
数据类型 | 说明 |
---|---|
char | 固定长度的字符串;这种类型的条目在右边用空格填充,以在存储时满足指定的长度。 |
varchar | 可变长度的字符串。 |
binary | 类似于 char 类型,但它是指定长度的二进制字节串,而不是非二进制字符串。 |
varbinary | 类似于 varchar 类型,但它是长度可变的二进制字节串,而不是非二进制字符串。 |
blob | 最大数据长度为65535(2^16 - 1)字节的二进制字符串。 |
tinyblob | 最大数据长度为255(2^8 - 1)字节的 blob 列。 |
mediumblob | 最大数据长度为16777215(2^24 - 1)字节的 blob 列。 |
longblob | 最大数据长度为4294967295(2^32 - 1)字节的 blob 列。 |
text | 最大长度为65535(2^16 - 1)个字符的字符串。 |
tinytext | 最大长度为255(2^8 - 1)个字符的 text 列。 |
mediumtext | 最大长度为16777215(2^24 - 1)个字符的 text 列。 |
longtext | 最大长度为4294967295(2^32 - 1)个字符的 text 列。 |
enum | 枚举,它是一个字符串对象,从创建表时声明的值列表中获取单个值。 |
set | 与枚举类似,一个字符串对象,可以有零个或多个值,每个值必须从创建表时指定的允许值列表中选择。 |
MySQL的优势
- 受欢迎程度和易用性:作为世界上最受欢迎的数据库系统之一,不乏有使用MySQL经验的数据库管理员。同样,关于如何安装和管理MySQL数据库,有大量的纸质文档和在线文档。这包括许多第三方工具——如phpMyAdmin——旨在简化使用数据库的过程。
- 安全性:MySQL安装了一个脚本,通过设置安装的密码安全级别,定义root用户的密码,删除匿名帐户,以及删除默认情况下所有用户都可以访问的测试数据库,来帮助您提高数据库的安全性。另外,与SQLite不同的是,MySQL支持用户管理,并允许您在每个用户的基础上授予访问权限。
- 速度:通过选择不实现SQL的某些特性,MySQL开发人员可以优先考虑速度。虽然最近的基准测试表明,PostgreSQL等其他rdbms在速度方面可以与MySQL相媲美,或者至少接近MySQL,但MySQL仍然被认为是一种非常快的数据库解决方案。
- 复制:MySQL支持多种不同类型的复制,通过在两个或多个主机之间共享信息来提高可靠性、可用性和容错性。这对于建立数据库备份解决方案或水平扩展数据库很有帮助。
MySQL的缺点
- 已知的限制:因为MySQL的设计目标是速度和易用性,而不是完全符合SQL规范,所以它在功能上有一定的限制。例如,它缺乏对
FULL JOIN
子句的支持。 - 许可和专有特性:MySQL是一个双许可的软件,它有一个免费和开源的社区版本,在GPLv2许可下发布,还有几个付费的商业版本,在专有许可下发布。因此,一些功能和插件只能在专有版本中使用。
- 开发速度慢:自从MySQL项目在2008年被Sun公司收购,2009年又被Oracle公司收购以来,用户一直抱怨数据库管理系统的开发进程明显慢了下来,因为社区不再有机构来快速应对问题和实施更改。
什么时候可以使用MySQL
- 分布式操作:MySQL的复制支持使其成为分布式数据库设置的一个很好的选择,例如primary-secondary或primary-primary架构。
- 网站和web应用程序:MySQL支持互联网上的许多网站和应用程序。这在很大程度上要归功于MySQL数据库的安装和设置非常容易,以及从长远来看它的整体速度和可扩展性。
- 预期未来增长:MySQL的复制支持有助于促进横向扩展。此外,升级到商业MySQL产品是一个相对简单的过程,比如MySQL集群,它支持自动分片(另一种水平扩展过程)。
什么时候不能使用MySQL
- 必须符合SQL规范:因为MySQL没有尝试实现完整的SQL标准,所以这个工具不是完全符合SQL规范的。如果你的用例必须完全遵从甚至接近完全遵从SQL,那么你可能希望使用更完全遵从SQL的DBMS。
- 并发和大数据量:虽然MySQL通常在繁重的读操作上表现良好,但并发的读写可能会带来问题。如果你的应用程序有很多用户同时写入数据,那么像PostgreSQL这样的RDBMS可能是更好的选择。
PostgreSQL
PostgreSQL,也被称为Postgres,自称是“世界上最先进的开源关系型数据库”。它的创建目标是高度可扩展和符合标准。PostgreSQL是一个对象关系型数据库,这意味着尽管它主要是一个关系型数据库,但它也包括一些特性,如表继承和函数重载,这些特性通常与对象数据库相关。
Postgres能够同时高效地处理多个任务,这种特性被称为并发。由于它实现了多版本并发控制(MVCC,它无需读锁就能实现这一点,该实现确保了事务的原子性、一致性、隔离性和持久性,也称为ACID一致性。
PostgreSQL不像MySQL那样被广泛使用,但是仍然有一些第三方工具和库旨在简化PostgreSQL的使用,包括pgAdmin和Postbird。
PostgreSQL支持的数据类型
PostgreSQL支持数字、字符串、日期和时间数据类型,如MySQL。此外,它还支持几何形状、网络地址、Bit串、文本搜索和JSON条目等数据类型。
数字类型:
数据类型 | 说明 |
---|---|
bigint | 有符号的8字节整数。 |
bigserial | 自动递增的8字节整数。 |
double precision | 8字节双精度浮点数。 |
integer | 有符号的4字节整数。 |
numeric 、decimal | 许多可选择的精度,建议在精确性至关重要的情况下使用,例如货币金额。 |
real | 4字节单精度浮点数。 |
smallint | 有符号的2字节整数。 |
smallserial | 自动递增的2字节整数。 |
serial | 自动递增的4字节整数。 |
字符类型:
数据类型 | 说明 |
---|---|
character | 具有指定的固定长度的字符串。 |
character varying 、varchar | 一种长度可变但有限的字符串。 |
text | 一种长度不受限制的可变字符串。 |
日期和时间类型:
数据类型 | 说明 |
---|---|
date | 由日、月和年组成的日历日期。 |
interval | 时间跨度。 |
time 、time without time zone | 一天中的时间,不包括时区。 |
time with time zone | 一天中的时间,包括时区。 |
timestamp 、timestamp without time zone | 日期和时间,不包括时区。 |
timestamp with time zone | 日期和时间,包括时区。 |
Geometric types:
数据类型 | 说明 |
---|---|
box | 平面上的长方形盒子。 |
circle | 平面上的圆。 |
line | 平面上的无限长线。 |
lseg | 平面上的线段。 |
path | 平面上的几何路径。 |
point | 平面上的几何点 |
polygon | 平面上的封闭几何路径。 |
网络地址类型:
数据类型 | 说明 |
---|---|
cidr | IPv4或IPv6网络地址。 |
inet | IPv4或IPv6主机地址。 |
macaddr | 介质访问控制(MAC)地址。 |
位串类型:
数据类型 | 说明 |
---|---|
bit | 固定长度的位串。 |
bit varying | 一种可变长度的位串。 |
文本搜索类型:
数据类型 | 说明 |
---|---|
tsquery | 文本搜索查询。 |
tsvector | 文本搜索文档。 |
JSON类型:
数据类型 | 说明 |
---|---|
json | 文本JSON数据。 |
jsonb | 分解的二进制JSON数据。 |
其他数据类型:
数据类型 | 说明 |
---|---|
boolean | 逻辑布尔值,表示 true 或 false 。 |
bytea | 是“byte array”的缩写,这种类型用于二进制数据。 |
money | 货币数量 |
pg_lsn | PostgreSQL日志序列号。 |
txid_snapshot | 用户级事务ID快照。 |
uuid | 通用唯一标识符。 |
xml | XML数据。 |
PostgreSQL的优势
- 符合SQL标准:与SQLite或MySQL相比,PostgreSQL的目标是严格遵循SQL标准。根据PostgreSQL官方文档, PostgreSQL支持full core SQL:2011合规所需的179个特性中的160个,此外还有一长列可选特性。
- 开源和社区驱动:PostgreSQL是一个完全开源的项目,它的源代码是由一个大型的社区开发的。类似地,Postgres社区维护并贡献了大量描述如何使用DBMS的在线资源,包括官方文档、PostgreSQL wiki和各种在线论坛。
- 可扩展性:用户可以通过目录驱动操作和动态加载以编程方式扩展PostgreSQL。你可以指定一个目标代码文件,比如一个共享库,PostgreSQL会根据需要加载它。
PostgreSQL的缺点
- 内存性能:对于每个新的客户端连接,PostgreSQL都会fork一个新的进程。每个新进程会分配大约10MB的内存,对于有大量连接的数据库来说,内存会迅速增加。因此,对于简单的重读操作,PostgreSQL的性能通常不如MySQL等其他rdbms。
- 流行度:尽管PostgreSQL近年来被广泛使用,但在流行度方面一直落后于MySQL。这样做的一个后果是,可以帮助管理PostgreSQL数据库的第三方工具仍然较少。类似地,与具有MySQL经验的数据库管理员相比,具有管理Postgres数据库经验的数据库管理员并不多。
什么时候可以使用PostgreSQL
- 数据完整性很重要:PostgreSQL自2001年以来就完全遵循ACID规范,并实现了多版本货币控制以确保数据保持一致,这使得它成为数据完整性至关重要的RDBMS的首选。
- 与其他工具的集成:PostgreSQL兼容各种编程语言和平台。这意味着,如果需要将数据库迁移到另一个操作系统或与特定工具集成,使用PostgreSQL数据库可能比使用其他DBMS更容易。
- 复杂的操作:Postgres支持利用多个cpu来以更快的速度回答查询的查询计划。这一点,再加上它对多个并发写入器的强大支持,使它成为数据仓库和在线事务处理等复杂操作的绝佳选择。
什么时候不能使用PostgreSQL
- 速度至关重要:PostgreSQL在设计时考虑了可扩展性和兼容性,这是以速度为代价的。如果你的项目需要尽可能快的读取操作,PostgreSQL可能不是最佳的DBMS选择。
- 简单设置:由于Postgres的功能集很大,并且严格遵循标准SQL,因此对于简单的数据库设置来说,Postgres可能是多余的。对于读取量大且要求速度快的操作,MySQL通常是更实用的选择。
- 复杂复制:尽管PostgreSQL提供了强大的复制支持,但它仍然是一个相对较新的功能。有些配置——比如primary-primary架构——只能通过扩展实现。复制是MySQL上一个比较成熟的功能,许多用户认为MySQL的复制更容易实现,特别是那些缺乏必要的数据库和系统管理经验的用户。
总结
如今,SQLite、MySQL和PostgreSQL是世界上最流行的三个开源关系型数据库管理系统。每个都有自己独特的功能和限制,并在特定场景中表现出色。在决定使用哪种RDBMS时,有很多变量在起作用,选择最快的或功能最多的RDBMS很少像选择那么简单。下次需要关系型数据库解决方案时,请务必深入研究这些工具和其他工具,以找到最适合您需求的工具。