为何PostgreSQL没有聚集索引?解读两大数据库的设计差异
为何PostgreSQL没有聚集索引?解读两大数据库的设计差异
前言
高效的数据检索是数据库管理的基石, PostgreSQL和SQL Server都能提供强大的数据访问方法以支持各种工作负载方面表现出色。然而,它们的实现方式存在显著差异,反映了各自独特的设计理念和使用场景。 在这篇文章中将介绍PostgreSQL提供的各种数据访问方法,其中包括一个非常独特的特点:PostgreSQL不支持聚集索引。这一根本性的差异对于理解PostgreSQL与SQL Server在数据存储和检索上的不同方式至关重要。
顺序扫描
任何数据库系统的核心都离不开最简单的数据访问方法,就是扫描表中的所有行。 PostgreSQL 通过顺序扫描(Sequential Scan)来实现这一点,它逐行读取表中的每一行。 虽然对于大型数据集而言,这看起来可能效率不高,但在特定场景下,它往往是最实际的选择。 当处理小型表时,使用索引的开销通常超过其带来的好处,因此顺序扫描非常有效。 此外,当查询需要表中大量行时,例如需要查询超过50%的数据行时候,顺序扫描可以通过最小化随机I/O来优于索引扫描。 SQL Server采用了一种类似的技术,称为表扫描(Table Scan),它逐行读取整个表。无论是PostgreSQL还是SQL Server都依赖其查询优化器来决定何时应选择表扫描而不是使用索引扫描。例如,在没有合适索引的情况下,或者查询涉及广泛的过滤条件时,优化器将选择全表扫描。尽管顺序扫描和表扫描有时被批评为较慢,但它们依然是数据库处理特定工作负载时必不可少的工具。
在PostgreSQL中,所有的表默认存储在堆结构(Heap)中,这意味着行没有固定的顺序。PostgreSQL中没有聚集索引的概念,这意味着顺序扫描通常会访问以任意顺序存储的行。
索引扫描
在PostgreSQL中,索引扫描(Index Scan)是一个基本的查询执行方法,它使用索引来高效地检索符合特定查询条件的行。 当执行索引扫描时,PostgreSQL会遍历索引结构(B树)来查找满足查询条件的行的位置(元组指针)。这些指针将引导PostgreSQL定位到堆表中的相应行,进而检索完整的行数据。 在PostgreSQL中,索引扫描的关键之处在于,它对堆表的查找操作是作为索引扫描的一部分内部执行的。因此,PostgreSQL 执行计划将索引扫描显示为一个单独的操作,它封装了索引遍历和随后从堆表中检索行数据这两个步骤。
与此不同,SQL Server的执行计划明确区分了这两个步骤。在SQL Server中,索引查找(Index Seek)操作负责遍历索引以找到匹配的行。当索引不包含查询所需的所有列时,SQL Server会引入一个单独的操作,对于聚集索引表是键查找(Key Lookup),对于堆表则是RID查找(RID Lookup)。这些查找操作会直接从基础表中获取额外的列。通过分离这些步骤,SQL Server的执行计划提供了一个更加清晰详细的视图,展示查询如何访问数据,包括索引遍历和数据行检索的成本和行为。 这种执行计划表示的差异凸显了不同的设计理念。 PostgreSQL将堆查找集成到索引扫描操作中,呈现一个简化的执行计划。然而,这也可能掩盖索引扫描中堆访问部分的具体成本。另一方面,SQL Server明确分离提供了对查询执行过程更为详细的洞察。例如,当SQL Server的执行计划中包含键查找时,立刻可以看出索引缺少一些必需的列,这可以帮助数据库管理员通过创建覆盖索引来消除查找操作。这种透明度对于识别和解决复杂查询中的性能瓶颈特别有帮助。
位图索引扫描与位图堆扫描
对于具有多个条件或过滤器的查询,PostgreSQL经常使用位图堆扫描(Bitmap Heap Scan),这是一种将索引访问的精确性与批量读取的高效性相结合的混合方法。 在执行此类查询时,PostgreSQL首先使用相关的索引构建一个位图,即匹配查询条件的行的压缩表示。与逐行访问不同,位图使PostgreSQL能够批量获取这些行从而减少随机磁盘 I/O。这种方法对于必须同时评估多个条件的大型表特别有用,例如按客户年龄和地点进行过滤。位图扫描Bitmap Scan也分为两个阶段,第一个阶段是Bitmap Index Scan,第二个阶段是Bitmap Heap Scan。Bitmap Heap Scan采用Bitmap Index Scan生成的bitmap(或者经过 BitmapAnd 和 BitmapOr 节点通过一系列位图集操作后,生成的bitmap)来查找相关数据。位图的每个page可以是精确的(直接指向tuple的)或有损的(指向包含至少一行与查询匹配的page)。
SQL Server并没有直接等同于位图堆扫描的操作,但它在并行查询执行计划中使用位图过滤(Bitmap Filtering)。位图堆扫描在处理需要多个索引扫描的查询时尤其具有优势,因为它将这些操作合并为一个更高效的过程。这种方法突显了 PostgreSQL 在动态优化复杂查询方面的独特能力。通过平衡顺序访问和索引访问的优点,位图堆扫描架起了精确性与高效性之间的桥梁,使其在分析和报告工作负载中变得不可或缺。
仅索引扫描
在PostgreSQL中,仅索引扫描(Index-Only Scans)是一种查询执行特性,允许数据完全从索引中检索,跳过对堆表的访问。 当查询只涉及索引中的列时,这种方法是可行的。在进行仅索引扫描时,PostgreSQL直接从索引的叶节点中获取数据,从而显著减少了I/O操作并提高了查询性能,特别适用于读密集型工作负载。例如,如果一个查询仅检索客户的姓名和电子邮件,并且这些列是索引的一部分,那么数据库完全避免了访问堆表的开销。在SQL Server中,类似的概念是通过覆盖索引(Covering Indexes)来实现的,在索引定义中包含了额外的列(超出索引键列的部分)。这些额外的列被称为包含列(Included Columns),它们允许 SQL Server 直接从索引中检索所有所需的数据,而无需执行键查找(Key Lookup)或 RID 查找(RID Lookup)。
并行查询执行
随着数据集的增大和查询变得更加复杂,采用并行处理对于保持性能至关重要。 PostgreSQL支持并行查询执行,允许多个工作进程分担和处理大规模的工作负载。例如,并行扫描将一个大型表分成多个分段,每个工作进程同时扫描其中的一部分。这种方法能够显著减少资源密集型操作的查询时间。SQL Server也支持执行计划中的并行处理,使用并行扫描(Parallel Scan)和合并流(Gather Streams)等操作符,将工作负载分配并合并到多个工作线程中。SQL Server的并行查询引擎与其优化器紧密集成,通常能为事务型OLTP和分析型OLAP工作负载生成高效的执行计划。
聚集索引的作用
PostgreSQL和SQL Server之间最显著的区别之一是PostgreSQL不支持聚集索引。 在SQL Server中,聚集索引定义了表中行的物理顺序。这可以显著提高范围查询或返回按排序顺序排列行的查询的性能,因为数据已经根据索引键物理排序。 在PostgreSQL中,所有表都以堆(heap)形式存储,这意味着行没有特定的存储顺序。虽然PostgreSQL提供了一个名为CLUSTER的命令,可以基于索引物理重新排序表,但这个操作不是动态的,必须手动执行。此外,CLUSTER创建的排序不会随着行的插入、更新或删除而保持。 PostgreSQL的这种设计选择优先考虑灵活性,而不是聚集索引可能带来的性能提升。 通过保持表的无序,PostgreSQL 允许多个索引并存,这对于大量数据写入的场景或者说写多读少的场景非常有利。
总结
PostgreSQL 和 SQL Server 中的数据访问方法展示了各自系统的优势和优先事项。PostgreSQL 的灵活性,例如位图堆扫描、仅索引扫描,使其成为开发者在查询执行上寻求精确控制的强大选择。 然而,PostgreSQL 不支持聚集索引是其与 SQL Server 的一个关键区别。另一方面,SQL Server 使用聚集索引来提供表行的物理排序,这可以显著有利于范围查询和排序操作。 这种结构性差异体现了两个系统的不同哲学:PostgreSQL 倾向于适应性,而 SQL Server 强调紧密集成的优化。理解这些差异能够帮助数据库专业人员做出明智的决策,并针对每个平台的独特优势优化查询。

本文版权归作者所有,未经作者同意不得转载。
为何PostgreSQL没有聚集索引?解读两大数据库的设计差异的更多相关文章
- navicat------------利用navicat查看两个数据库之间的差异
- mysql----------利用navicat查看两个数据库之间的差异
- Key Lookup开销过大导致聚集索引扫描
以前总结过一篇文章SQL SERVER中什么情况会导致索引查找变成索引扫描 介绍了几种索引查找(Index Seek)变成索引扫描(Index Scan)的情形.昨天写一篇文章的时候,也遇到了一个让人 ...
- SQL索引学习-聚集索引
这篇接着我们的索引学习系列,这次主要来分享一些有关聚集索引的问题.上一篇SQL索引学习-索引结构主要是从一些基础概念上给大家分享了我的理解,没有实例,有朋友就提到了聚集索引的问题,这里列出来一下: 其 ...
- SQL Server索引进阶:第三级,聚集索引
原文地址: Stairway to SQL Server Indexes: Level 3, Clustered Indexes 本文是SQL Server索引进阶系列(Stairway to SQL ...
- SQLServer中重建聚集索引之后会影响到非聚集索引的索引碎片吗
本文出处:http://www.cnblogs.com/wy123/p/7650215.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- mysql聚集索引
转自http://www.cnblogs.com/tuyile006/archive/2009/08/28/1555615.html 微软的SQL SERVER提供了两种索引:聚集索引(cluster ...
- SQL Server - 索引详细教程 (聚集索引,非聚集索引)
转载自:https://www.cnblogs.com/hyd1213126/p/5828937.html 作者:爱不绝迹 (一)必读:深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录. ...
- SQL Server的聚集索引和非聚集索引
微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclustered index,也称非聚类索引.非簇集索引)…… (一) ...
- SQL存储原理及聚集索引、非聚集索引、唯一索引、主键约束的关系(补)
索引类型 1. 唯一索引:唯一索引不允许两行具有相同的索引值 2. 主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型.主键索引要求主键中的 ...
随机推荐
- Vue3条件与列表渲染深度解析:实战技巧助你高效开发复杂界面
一.条件渲染的高阶应用 1.1 多分支条件渲染(v-if/v-else-if/v-else) <!-- 评分等级展示案例 --> <div v-if="score > ...
- containerd 配置使用私有镜像仓库 harbor
前言 当要从非安全的镜像仓库中进行 Pull.Push 时,会遇到 x509: certificate signed by unknown authority 错误提示: 这是由于镜像仓库是可能是 ...
- SQLSTATE[HY000] [2002] Connection refused报错 PHP连接docker容器中的mysql
Laradock 是基于 Docker 提供的完整 PHP 本地开发环境 在框架中连接 MySQL 时 报错 SQLSTATE[HY000] [2002] Connection refused 主要还 ...
- Ansible运行临时命令
一.基本语法格式: 格式:ansible 受控主机IP/主机组 [选项] 参数 选项 -k 手动输入SSH协议的代码 -l 指定主机清单文件 -m 指定要使用的模块名 -a 设置传递给模块的参数 -M ...
- Oracle10g RAC -- Linux 集群文件系统
通常,集群只是一组作为单一系统运行的服务器( PC 或者工作站).但是,这个定义的外延不断显著扩大:集群技术现在不但是一个动态领域,而且其各种应用程序正不断吸收新的特性.此外,集群文件系统技术(无论是 ...
- [每日算法] leetcode第2题:两数相加
leetcode第2题入口 题目描述 给你两个 非空 的链表,表示两个非负的整数.它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字. 请你将两个数相加,并以相同形式返回一个表 ...
- Random和猜数字小游戏
1.Random:使用方式和Scanner一样 Random用于生成随机数,括号里的10就是指在10以内随机生成一个数(0~9) Random生成的随机数都是从0开头 . 提问:那该如何让Random ...
- 【数据结构与算法】找出最小的k个数:三路快速排序算法思想实现
找出最小的k个数:三路快速排序算法思想实现 Java https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/zui-xi ...
- leetcode每日一题:使所有字符相等的最小成本
题目 2712. 使所有字符相等的最小成本 给你一个下标从 0 开始.长度为 n 的二进制字符串 s ,你可以对其执行两种操作: 选中一个下标 i 并且反转从下标 0 到下标 i(包括下标 0 和下标 ...
- 中文Markmap v2.0 现已上线,新增高效功能,老板再也留不住你下班的脚步!
介绍 Markmap.js 是一款开源项目,在 GitHub 上获得了超过 1.7 万个星的关注,它的主要功能是将 Markdown 文档可视化为思维导图. 在日常使用中,用户经常需要面对老板的&qu ...