【问题标题】:Tuning subquery in postgres在 postgres 中调整子查询
【发布时间】:2011-05-15 17:39:01
【问题描述】:

我在数据库中发现了一些可疑数据。我正在尝试确定某个字段(姓氏)是否正确。我在 postgres 中提出了以下查询:

SELECT members."memberID", 
       members.lastname 
  FROM members 
 WHERE members."memberID" NOT IN (SELECT members."memberID" 
                                    FROM members 
                                   WHERE members.lastname ~* '[a-zA-z]+([-][a-zA-Z]+)*');

子查询当前匹配普通名称和带有连字符的名称。父查询应显示与该模式不匹配的成员。目前,查询需要花费大量时间来运行(我从未见过它完整)。我不知道为什么需要这么长时间或如何改进它。

【问题讨论】:

  • @OMG 我的编辑怎么了?
  • @OMG:实际上......忽略。我很傻:)

标签: sql postgresql subquery


【解决方案1】:

不存在

SELECT m."memberID", 
       m.lastname 
  FROM MEMBERS m 
 WHERE NOT EXISTS (SELECT NULL
                     FROM MEMBERS b
                    WHERE b.lastname ~* '[a-zA-z]+([-][a-zA-Z]+)*'
                      AND b."memberID" = m."memberID");

左连接/为空

   SELECT m."memberID", 
          m.lastname 
     FROM MEMBERS m 
LEFT JOIN MEMBERS b ON b."memberID" = m."memberID"
                   AND b.lastname ~* '[a-zA-z]+([-][a-zA-Z]+)*'
    WHERE b."memberID" IS NULL

总结

Quote:

PostgreSQL 同等对待LEFT JOINNOT EXISTS,对它们使用相同的执行计划(即上面示例的哈希反连接)。

至于NOT IN,它在语义上是不同的,因为它的逻辑是三价的并且它可以返回 NULL,PostgreSQL 试图考虑到这一点,并限制自己对子计划使用过滤器(哈希结果集的哈希子计划,如在上面的例子中)。

由于每个缺失值需要在哈希表中搜索两次(第一次找值,第二次找NULL),所以这种方法效率有点低。

一个简单的子计划,优化器可以在它决定列表不适合内存的任何时候使用,效率非常低,应该像瘟疫一样避免使用它的查询。

这就是为什么在 PostgreSQL 8.4 中应该始终使用LEFT JOIN / IS NULLNOT EXISTS 而不是NOT IN 来查找缺失值。

附录

但正如 Andrew Lazarus 指出的,如果 MEMBERS 表中没有 memberid 重复项,则查询只需:

SELECT m."memberID", 
       m.lastname 
  FROM MEMBERS m 
 WHERE b.lastname ~* '[a-zA-z]+([-][a-zA-Z]+)*'

【讨论】:

  • 认为NOT EXISTS 版本中有错字。 WHERE NOT EXISTS ... 不是 WHERE m.memberId NOT EXISTS ...
【解决方案2】:

我喜欢 OMG Ponies 的回答,但 如果 memberID 是唯一的(即 PK),您可以完全放弃子查询。

SELECT members."memberID", 
       members.lastname 
  FROM members 
 WHERE members.lastname !~ '[a-zA-Z]+([-][a-zA-Z]+)*';

(我删除了不区分大小写的运算符,因为正则表达式涵盖了这两种情况。)

【讨论】:

    猜你喜欢
    • 2022-10-15
    • 2020-02-03
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 2015-12-19
    • 1970-01-01
    相关资源
    最近更新 更多