Sql 我的用例可以合并到一个查询中而不影响性能吗?

Sql 我的用例可以合并到一个查询中而不影响性能吗?,sql,database,performance,postgresql,Sql,Database,Performance,Postgresql,我主要着眼于提高查询的性能,以及是否能够在单个查询中解决我下面解释的一个用例: 涉及两个表格: Table 1: EMPLOYEE (column1, column2, email1, email2, column5, column6) Table 2: EMAILLIST (email) 我的要求是,我想从EMPLOYEE表中获取/获取所有记录,条件是email1或email2在EMAILLIST表中没有匹配的条目。简单地说,若email1或email2在EMAILLIST表中匹配,那个么这

我主要着眼于提高查询的性能,以及是否能够在单个查询中解决我下面解释的一个用例:

涉及两个表格:

Table 1: EMPLOYEE (column1, column2, email1, email2, column5, column6)
Table 2: EMAILLIST (email)
我的要求是,我想从EMPLOYEE表中获取/获取所有记录,条件是email1或email2在EMAILLIST表中没有匹配的条目。简单地说,若email1或email2在EMAILLIST表中匹配,那个么这些记录应该被忽略

在这种情况下,EMPLOYEE.EMAIL1、EMPLOYEE.EMAIL2和EMAILLIST.EMAIL将始终存储单个电子邮件地址

如果有必要的话,我们正在使用PostgreSQL v8.2.3

任何提示/想法/逻辑都值得赞赏


更新:目前,我们的实现方式是:从EMPLOYEE表中获取所有记录并存储在Java对象中,对于每个条目(for循环),这将依次在EMAILLIST表中进行检查,这在性能上是非常昂贵的。

对于我处理过的每个rdbms,最有效的处理方法是使用外部联接:

SELECT whatever
FROM employee AS e
LEFT JOIN emaillist AS em1 ON e.email1 = em1.email
LEFT JOIN emaillist AS em2 ON e.email2 = em2.email
WHERE em1.id IS NULL
    AND em2.id IS NULL

一般来说,我认为您会发现,任何将数据库查询放入循环的情况都是次优的

有三种方法可以解决这个问题

左连接 不存在 不在
从OP的描述“如果emaillist中有……匹配项,那么这些记录应该被忽略”,我认为您希望在WHERE子句中使用AND,而不是OR。我更改了它-问题陈述有点混乱。无论如何,如果不是,则可能是或。:)@le dorfier:在您的查询中,什么是
em1.id
em2.id
?外部联接尝试匹配emaillist表中的两个不同记录。与内部联接不同,外部联接将从主表(employee)返回行,即使没有找到匹配项。如果匹配了em1中的记录,那么em1.email将返回email字段值(您碰巧加入了该字段,但这并不重要)。如果join不匹配,则emaillist中的任何字段都将为null(因为没有记录)。因此,要测试“未找到记录”,请测试其他不可为null的字段是否为null。从逻辑上讲,它们都是等效的。问题是查询优化器如何分解和执行SQL表达式。如果他做了两个外连接,那就相当了。查询优化器通常不会在确定索引选择的任何位置重建或表达式,因为它们的效率较低#1在WHERE子句中使用OR,另外两个具有相关子查询(需要避免的事情)。@le dorfier。再查一遍。第一个在FROM子句中使用OR。不确定所谓的低效率。它可以根据数据和后端的不同而变化很大。最好先测试,然后再假设什么是最快的,然后再解释,看看哪一个效果最好。NOT IN()可能是个问题,当你有很多值时不要使用这个。你的第一个查询不是基于
LEFT JOIN
吗类似于@le dorfier的解决方案吗?不在,甚至可能不存在可能是PostgreSQL 8.2上的一个问题-在更现代的版本中,它们都处理得更好。LEFT JOIN可能是这个版本中速度最快的一个,但正如Frank所建议的,请使用EXPLAIN找出给您提供最佳计划的方法。Offtopic:PostgreSQL v8.2.3已经有4年历史,落后16轮补丁。在你遇到麻烦之前考虑一下维护。
SELECT *
FROM employee AS e
LEFT JOIN emaillist AS em 
ON e.email1 = em.email
   or e.Email2 = em.email
 WHERE
     em.email is null
SELECT *
FROM employee AS e
WHERE
   NOT EXISTS (SELECT * 
               FROM  
                 emaillist AS em 
              WHERE e.email1 = em.email
                  or e.email2 = em.Email)
SELECT *
FROM employee AS e
WHERE
    e.email1 NOT IN (SELECT email
               FROM  
                 emaillist)
    and
     e.email2 NOT IN (SELECT email
               FROM  
                 emaillist)