sql - OR 语句大大减慢了查询速度

标签 sql postgresql

如果像这样在 where 子句中包含 OR,我有这个查询,它的行为非常不同

SELECT t.id
FROM teams AS t
LEFT OUTER JOIN teams_users AS tu ON tu.team_id = t.id
LEFT OUTER JOIN user AS u ON tu.user_id = u.id
WHERE 
    u.id = '8601680c9cd549c0a786288e1775fb63' OR t.id = '8601680c-9cd5-49c0-a786-288e1775fb63'

以上将在 ~500 毫秒内运行。如果我删除 OR 并仅按用户 ID 进行过滤,如下所示:

WHERE u.id = '8601680c9cd549c0a786288e1775fb63'

它在 20 毫秒内运行。如果我像这样只按团队 ID 过滤:

WHERE t.id = '8601680c-9cd5-49c0-a786-288e1775fb63'

它也在 20 毫秒内运行。但出于某种原因,如果我同时过滤两者,它会变得更慢

关于原因有什么想法吗?

最佳答案

在许多情况下,这是因为解释计划无法轻松处理这两种情况。

  • 针对一种情况的最佳计划与针对另一种情况的计划会有很大不同。

要知道或确定您需要查看所有三个解释计划,如果您希望我们弄清楚,您需要在问题中提供它们。

  1. 您使用 OR 进行主查询
  2. 仅根据 t.id 过滤
  3. 仅根据 u.id 过滤

使用 IN() 的示例避免了键入关键字 OR,但仍会产生相同的逻辑并且通常容易出现相同的规划问题。

如果是这种情况,一种选择是使用 UNION。这允许您的结果包含来自两个单独查询的结果,DBMS 可以单独计划...

SELECT t.id
FROM teams AS t
WHERE t.id = '8601680c-9cd5-49c0-a786-288e1775fb63'

UNION

SELECT t.id
FROM teams AS t
INNER JOIN teams_users AS tu ON tu.team_id = t.id
INNER JOIN user AS u ON tu.user_id = u.id
WHERE u.id = '8601680c9cd549c0a786288e1775fb63'

这也允许 LEFT OUTER JOIN 变成 INNER JOIN。这是解释计划在您的第一个示例中受到影响的示例;需要 LEFT JOIN 只是因为您想解决这两个条件,但允许分别解决它们允许 INNER JOIN

您还可以在第二个查询中删除对 teams 的连接,然后从 tu.team_id AS id 中选择...

编辑:

SELECT id
  FROM teams
 WHERE id = '8601680c-9cd5-49c0-a786-288e1775fb63'

UNION

SELECT team_id
  FROM teams_users
 WHERE user_id = '8601680c9cd549c0a786288e1775fb63'

我还注意到,您过滤 teams 表所依据的列也是您从中选择的列。那么,您是否真的需要完全引用团队表(SELECT '8601680c-9cd5-49c0-a786-288e1775fb63' AS id UNION ...)(或者您只是在检查这样的团队是否存在?)

关于sql - OR 语句大大减慢了查询速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48984162/

相关文章:

SQL 在表中查找五个最大的数字而不是一个 Max

mysql - 在 Joomla 3.2 中编辑文章 SQL 错误

sql - Postgresql - 为每个 ID 返回 (N) 行

sql - 是否可以将 CASE 与 WHERE 一起使用?

spring - 非常慢的 Spring Boot 应用程序启动

sql - 如何替换 SQL Server 中特定字符前后的子字符串?

mysql - 插入触发器不起作用

mysql - 添加到长而复杂的查询

hibernate - grails 2.4.3 升级后不必要的数据库 changeSet 与 boolean 相关

node.js - 如何将 JSONB 操作与 pg-promise 结合使用