PostgreSQL 表连接性能差?四种方法来改进

数据库 MySQL
MySQL 和 PostgreSQL 都提供了多种连接类型,允许您精确定义要从连接两侧检索出来的行集。它们都在这样或那样的情况下很有用,但并非所有连接类型都具有相同的性能。

在关系数据库中,连接经常用于查询来自不同表的数据。了解可用的连接类型及其含义,对于实现最佳性能至关重要。以下建议可帮助您识别出正确的连接类型。

选择内连接

原因

MySQL 和 PostgreSQL 都提供了多种连接类型,允许您精确定义要从连接两侧检索出来的行集。它们都在这样或那样的情况下很有用,但并非所有连接类型都具有相同的性能。INNER JOIN在仅检索两侧数据集都包含的行时,通常具有最佳性能。另一方面,与INNER JOIN相比,LEFT、RIGHT和OUTER类型的连接需要执行一些额外的工作,因此只有在真正必要时才应使用它们。

Type of Joins in relational databases

警告

仔细检查您的查询,有时如下所示的查询似乎是合理的:

SELECT * 
FROM ORDERS LEFT JOIN USERS ON ORDERS.NAME = USERS.NAME
WHERE USERS.NAME IS NOT NULL

上面使用了一个LEFT JOIN从ORDERS表中检索所有行,但随后筛选了满足USERS.NAME IS NOT NULL的行。因此这等效于一个INNER JOIN。

最佳实践

请评估对JOIN语句的真实要求,并分析现有的WHERE条件。如果不是绝对必要的话,请首选INNER JOIN。

专业建议

还要检查是否可以完全避免连接。例如,如果我们连接数据只是为了验证某一行在另一个表中是否存在,则使用一个EXISTS子查询可能比连接快得多。

在连接时使用相同的列类型

原因

在连接两个表时,请确保连接条件中的列为相同类型。将一个表中的一个整型Id列,与另一个表中一个定义为VARCHAR的customerId列连接起来,会强制数据库在比较结果之前,将每个Id列转换为字符串,导致性能降低。

Set of steps required for non matching column types join condition

警告

您无法在查询时更改源表的字段类型,但可以公开数据类型不一致的问题,并在数据库表中修复它。在分析CustomerId字段是否可以从VARCHAR迁移到INT时,请检查列中的所有值是否确实是整数。如果某些值不是整数,也可能存在数据质量方面的问题。

专业建议

如有疑问,请为连接键选择更紧凑的表示形式。如果要存储的内容可以明确定义为数字(例如,像1234-678-234这样的产品代码),则首选数字的表示形式,因为它将:

  • • 使用更少的磁盘空间
  • • 更快地检索
  • • 连接速度更快,因为整数的比较比字符串要更快

但是,要小心看起来像数字但行为不太像的东西。例如,像015555555这样的电话号码,其中的前缀零很重要。

避免在连接中使用函数

原因

与上一节类似,应避免在连接中使用不必要的函数。函数会阻止数据库优化性能,比如利用索引。只需考虑下面的查询:

SELECT * 
FROM users 
JOIN orders ON UPPER(users.user_name) = orders.user_name

上面使用了一个函数,将user_name字段转换为大写。但是,这可能是orders表中数据质量差(和缺少外键)的信号,这应该解决。

警告

像上面这样的查询,展示出数据质量方面的问题,在查询时候的解决方法,只是一个短期的解决方案。在设计数据类后端系统时,正确地处理数据类型和质量约束,应该是优先事项。

最佳实践

在关系数据库中,表之间的连接应该可以使用键和外键来实现,而无需任何其他函数。如果您发现自己需要使用函数,请修复表中的数据质量问题。在某些边缘情况下,将函数与索引结合使用,有助于加快复杂或冗长的数据类型之间的比较。例如,最初仅使用连接函数UPPER(SUBSTR(users.user_name, 1, 50)),以及同一函数上的索引,来比较前面 50 个字符,可以加快两个长字符串之间的相等性检查。

避免连接

原因

随着时间的推移,查询会由不同的人来构建,并且在 CTE(公共表表达式)的形式中,会有许多连续的步骤。因此,可能很难理解数据输入和输出方面的实际需求。大多数情况下,在编写一个查询时,您可以在后续阶段添加一个额外的字段,“以防万一”。但是,如果这个字段来自需要进行连接的新表,这可能会对性能产生巨大影响。

应该始终评估查询严格的数据需求,并仅包含那些包含此信息的列和表。

Avoid unnecessary joins

警告

仔细检查,是否需要连接来筛选两个表中存在的行。在上面的示例中,如果有orders表中存在的user_id,未存储在users表的id列中,则最终可能会得到不正确的结果。

最佳实践

删除不必要的连接。生成更精简的查询来检索整个数据集,然后仅在必要时执行查找以获取更多信息,性能要高得多。

专业建议

上面解释的示例,只是过度使用JOIN的一种情况。另一个示例是,当我们连接数据只是为了验证在另一个表中是否存在行。在这种情况下,一个使用EXISTS的子查询可能比连接要快得多。

责任编辑:武晓燕 来源: 红石PG
相关推荐

2010-07-16 13:50:53

Perl哈希表

2010-08-31 15:51:51

DB2清除数据

2014-03-17 09:22:43

Linux命令

2022-09-02 14:29:01

JavaScrip数组属性

2023-02-03 08:47:20

职位招聘难题

2011-06-22 15:21:08

XML

2009-03-31 13:12:30

解析XMLJava

2009-02-25 09:52:14

类型转换.NET 强制转型

2020-08-10 00:30:55

备份密码iPhone移动安全

2016-06-28 10:19:31

云计算云安全

2009-11-23 15:57:51

PHP伪静态

2021-03-10 10:13:39

爬虫Python代码

2020-07-24 09:56:12

React开发数据

2021-09-03 11:24:04

云计算云计算环境云应用

2014-02-28 10:50:24

Linux命令

2010-03-18 17:57:37

Java XMLSoc

2010-08-02 16:47:46

Flex

2010-09-02 10:55:57

CSS

2009-09-17 16:55:58

C#组件设计

2010-08-26 14:18:25

DIV高度
点赞
收藏

51CTO技术栈公众号