PostgreSQL 10.1 手册_部分 II. SQL 语言_第 14 章 性能提示_14.3. 用显式JOIN子句控制规划器

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 14.3. 用显式JOIN子句控制规划器 我们可以在一定程度上用显式JOIN语法控制查询规划器。要明白为什么需要它,我们首先需要一些背景知识。 在一个简单的连接查询中,例如: SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id; 规划器可以自由地按照任何顺序连接给定的表。

14.3. 用显式JOIN子句控制规划器

我们可以在一定程度上用显式JOIN语法控制查询规划器。要明白为什么需要它,我们首先需要一些背景知识。

在一个简单的连接查询中,例如:

SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;

规划器可以自由地按照任何顺序连接给定的表。例如,它可以生成一个使用WHERE条件a.id = b.id连接 A 到 B 的查询计划,然后用另外一个WHERE条件把 C 连接到这个连接表。或者它可以先连接 B 和 C 然后再连接 A 得到同样的结果。 或者也可以连接 A 到 C 然后把结果与 B 连接 — 不过这么做效率不好,因为必须生成完整的 A 和 C 的迪卡尔积,而在WHERE子句中没有可用条件来优化该连接(PostgreSQL执行器中的所有连接都发生在两个输入表之间, 所以它必须以这些形式之一建立结果)。 重要的一点是这些不同的连接可能性给出在语义等效的结果,但在执行开销上却可能有巨大的差别。 因此,规划器会对它们进行探索并尝试找出最高效的查询计划。

当一个查询只涉及两个或三个表时,那么不需要考虑很多连接顺序。但是可能的连接顺序数随着表数目的增加成指数增长。 当超过十个左右的表以后,实际上根本不可能对所有可能性做一次穷举搜索,甚至对六七个表都需要相当长的时间进行规划。 当有太多的输入表时,PostgreSQL规划器将从穷举搜索切换为一种遗传概率搜索,它只需要考虑有限数量的可能性(切换的阈值用geqo_threshold运行时参数设置)。遗传搜索用时更少,但是并不一定会找到最好的计划。

当查询涉及外连接时,规划器比处理普通(内)连接时拥有更小的自由度。例如,考虑:

SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

尽管这个查询的约束表面上和前一个非常相似,但它们的语义却不同, 因为如果 A 里有任何一行不能匹配 B 和 C的连接表中的行,它也必须被输出。因此这里规划器对连接顺序没有什么选择:它必须先连接 B 到 C,然后把 A 连接到该结果上。 相应地,这个查询比前面一个花在规划上的时间更少。在其它情况下,规划器就有可能确定多种连接顺序都是安全的。例如,给定:

SELECT * FROM a LEFT JOIN b ON (a.bid = b.id) LEFT JOIN c ON (a.cid = c.id);

将 A 首先连接到 B 或 C 都是有效的。当前,只有FULL JOIN完全约束连接顺序。大多数涉及LEFT JOINRIGHT JOIN的实际情况都在某种程度上可以被重新排列。

显式连接语法(INNER JOINCROSS JOIN或无修饰的JOIN)在语义上和FROM中列出输入关系是一样的, 因此它不约束连接顺序。

即使大多数类型的JOIN并不完全约束连接顺序,但仍然可以指示PostgreSQL查询规划器将所有JOIN子句当作有连接顺序约束来对待。例如,这里的三个查询在逻辑上是等效的:

SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;
SELECT * FROM a CROSS JOIN b CROSS JOIN c WHERE a.id = b.id AND b.ref = c.id;
SELECT * FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

但如果我们告诉规划器遵循JOIN的顺序,那么第二个和第三个还是要比第一个花在规划上的时间少。 这个效果对于只有三个表的连接而言是微不足道的,但对于数目众多的表,可能就是救命稻草了。

要强制规划器遵循显式JOIN的连接顺序, 我们可以把运行时参数join_collapse_limit设置为 1(其它可能值在下文讨论)。

你不必为了缩短搜索时间来完全约束连接顺序,因为可以在一个普通FROM列表里使用JOIN操作符。例如,考虑:

SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...;

如果设置join_collapse_limit = 1,那么这就强迫规划器先把 A 连接到 B, 然后再连接到其它的表上,但并不约束它的选择。在这个例子中,可能的连接顺序的数目减少了 5 倍。

按照这种方法约束规划器的搜索是一个有用的技巧,不管是对减少规划时间还是对引导规划器生成好的查询计划。 如果规划器按照默认选择了一个糟糕的连接顺序,你可以通过JOIN语法强迫它选择一个更好的顺序 — 假设你知道一个更好的顺序。我们推荐进行实验。

一个非常相近的影响规划时间的问题是把子查询压缩到它们的父查询中。例如,考虑:

SELECT *
FROM x, y,
    (SELECT * FROM a, b, c WHERE something) AS ss
WHERE somethingelse;

这种情况可能在使用包含连接的视图时出现;该视图的SELECT规则将被插入到引用视图的地方,得到与上文非常相似的查询。 通常,规划器会尝试把子查询压缩到父查询里,得到:

SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;

这样通常会生成一个比独立的子查询更好些的计划(例如,outer 的WHERE条件可能先把 X 连接到 A 上,这样就消除了 A 中的许多行, 因此避免了形成子查询的全部逻辑输出)。但是同时,我们增加了规划的时间; 在这里,我们用五路连接问题替代了两个独立的三路连接问题。这样的差别是巨大的,因为可能的计划数的是按照指数增长的。 如果有超过from_collapse_limitFROM项将会导致父查询,规划器将尝试通过停止提升子查询来避免卡在巨大的连接搜索问题中。你可以通过调高或调低这个运行时参数在规划时间和计划的质量之间取得平衡。

from_collapse_limitjoin_collapse_limit的命名相似,因为它们做的几乎是同一件事:一个控制规划器何时将把子查询平面化,另外一个控制何时把显式连接平面化。通常,你要么把join_collapse_limit设置成和from_collapse_limit一样(这样显式连接和子查询的行为类似), 要么把join_collapse_limit设置为 1(如果你想用显式连接控制连接顺序)。 但是你可以把它们设置成不同的值,这样你就可以细粒度地调节规划时间和运行时间之间的平衡。

本文转自PostgreSQL中文社区,原文链接:14.3. 用显式JOIN子句控制规划器

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
1月前
|
SQL Oracle 关系型数据库
SQL语言的主要标准及其应用技巧
SQL(Structured Query Language)是数据库领域的标准语言,广泛应用于各种数据库管理系统(DBMS)中,如MySQL、Oracle、SQL Server等
|
1月前
|
SQL 关系型数据库 MySQL
Go语言项目高效对接SQL数据库:实践技巧与方法
在Go语言项目中,与SQL数据库进行对接是一项基础且重要的任务
67 11
|
2月前
|
SQL 关系型数据库 C语言
PostgreSQL SQL扩展 ---- C语言函数(三)
可以用C(或者与C兼容,比如C++)语言编写用户自定义函数(User-defined functions)。这些函数被编译到动态可加载目标文件(也称为共享库)中并被守护进程加载到服务中。“C语言函数”与“内部函数”的区别就在于动态加载这个特性,二者的实际编码约定本质上是相同的(因此,标准的内部函数库为用户自定义C语言函数提供了丰富的示例代码)
|
3月前
|
SQL 关系型数据库 MySQL
|
3月前
|
SQL 存储 大数据
SQL 语言发展史简直太震撼啦!从诞生到现代数据处理,见证一场奇妙的演变之旅,快来感受!
【8月更文挑战第31天】SQL(结构化查询语言)自20世纪70年代由IBM研究员E.F. Codd提出以来,已成为现代数据处理不可或缺的一部分。它最初简化了层次和网状模型中复杂的存储与检索问题,通过基本的SELECT、FROM和WHERE关键字实现了数据查询。80年代,SQL在商业数据库中广泛应用,引入了GROUP BY、HAVING和ORDER BY等功能,增强了数据分析能力。90年代,互联网和企业信息化推动了SQL的进一步优化与扩展,支持分布式数据库和数据仓库等技术。
56 0
|
3月前
|
SQL 存储 NoSQL
从SQL到NoSQL:理解不同数据库类型的选择与应用——深入比较数据模型、扩展性、查询语言、一致性和适用场景,为数据存储提供全面决策指南
【8月更文挑战第31天】在信息技术飞速发展的今天,数据库的选择至关重要。传统的SQL数据库因其稳定的事务性和强大的查询能力被广泛应用,而NoSQL数据库则凭借其灵活性和水平扩展性受到关注。本文对比了两种数据库类型的特点,帮助开发者根据应用场景做出合理选择。SQL数据库遵循关系模型,适合处理结构化数据和复杂查询;NoSQL数据库支持多种数据模型,适用于非结构化或半结构化数据。SQL数据库在一致性方面表现优异,但扩展性较差;NoSQL数据库则设计之初便考虑了水平扩展性。SQL使用成熟的SQL语言,NoSQL的查询语言更为灵活。
80 0
|
3月前
|
SQL 数据可视化 数据挖掘
SQL 在数据分析中简直太牛啦!从数据提取到可视化,带你领略强大数据库语言的神奇魅力!
【8月更文挑战第31天】在数据驱动时代,SQL(Structured Query Language)作为强大的数据库查询语言,在数据分析中扮演着关键角色。它不仅能够高效准确地提取所需数据,还能通过丰富的函数和操作符对数据进行清洗与转换,确保其适用于进一步分析。借助 SQL 的聚合、分组及排序功能,用户可以从多角度深入分析数据,为企业决策提供有力支持。尽管 SQL 本身不支持数据可视化,但其查询结果可轻松导出至 Excel、Python、R 等工具中进行可视化处理,帮助用户更直观地理解数据。掌握 SQL 可显著提升数据分析效率,助力挖掘数据价值。
74 0
|
3月前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
404 0
|
SQL Cloud Native 关系型数据库
ADBPG(AnalyticDB for PostgreSQL)是阿里云提供的一种云原生的大数据分析型数据库
ADBPG(AnalyticDB for PostgreSQL)是阿里云提供的一种云原生的大数据分析型数据库
1277 1
|
数据可视化 关系型数据库 MySQL
将 PostgreSQL 迁移到 MySQL 数据库
将 PostgreSQL 迁移到 MySQL 数据库
1761 2
下一篇
无影云桌面