SQL 性能差异 WHERE IN UNION 与 WHERE IN 临时表来自 with 子句

问题描述

在当前项目中,我和我的团队对 MariaDB 进行了以下查询,该查询在本地环境中的性能相当差(~700 毫秒)。

SELECT i.id,i.contact_person,i.description,i.status
FROM issues_with_status i
WHERE i.status = 'NEW'
  AND i.id NOT IN (
    SELECT issue_id
    FROM recurring_issues
    UNION
    disTINCT
    SELECT disTINCT sub_issue_id
    FROM recurring_issues
    WHERE sub_issue_id IS NOT NULL
)

我的一位同事提出了将 NOT IN 部分移到单独的 WITH 子句中的解决方案。这将运行时间减少到上述查询 700 毫秒的 10% 左右:

WITH sub_issues AS (
      SELECT issue_id
      FROM recurring_issues
      UNION
      SELECT sub_issue_id
      FROM recurring_issues
      WHERE sub_issue_id IS NOT NULL
)
SELECT
        i.id,i.status
    FROM issues_with_status i
    WHERE i.status = 'NEW'
    AND i.id NOT IN ( select issue_id from sub_issues )

但是,由于我们并不是真正的 sql 专家,因此我们并不真正了解性能提高的原因。有人可以分享有关 MariaDB(或一般的 sql)内部工作的见解来解释这一点吗?我想这与第二个版本中 disTINCT 关键字的缺失无关,或者是吗?

解决方法

这不能回答您关于性能的问题。

但是,我建议使用两个单独的 exists 子句(或者可能是 in):

SELECT i.id,i.contact_person,i.description,i.status
FROM issues_with_status i
WHERE i.status = 'NEW' AND
      (NOT EXISTS (SELECT 1
                   FROM recurring_issues ri
                   WHERE ri.issue_id = i.id
                  ) AND
       NOT EXISTS (SELECT 1
                   FROM recurring_issues ri
                   WHERE ri.sub_issue_id = i.id
                  )
      );

反过来,这可以使用 recurring_issues(issue_id)recurring_issues(sub_issue_id) 上的索引。