使用OR的SQL查询速度很慢,但在Oracle数据库中使用UNION非常快

时间:2017-07-27 16:32:51

标签: sql oracle

我有一个问题,我想在查询中添加OR,但这会让它运行得非常慢。 查询看起来像这样:

SELECT TRIM(l.ID) ID,
       TRIM(C.UID) UID,
       TRIM(c.UPLOADED_ID) UPLOADED_ID,
       TRIM(l.record_key) record_key,
       TRIM(c.customers_record_key) customers_record_key,
       c.prohibitautoupdate,
       TRIM(c.c_additional_key) c_additional_key,
       TRIM(c.record_status) c_record_status    
FROM tmp_customers_upload l, customers c

WHERE (l.record_key = c.customers_record_key AND NVL(TRIM(l.ID),' ') <> c.UPLOADED_ID AND c.UPLOADED_ID IS NOT NULL )
OR (SUBSTR(C.UID, 6, 11) = TRIM(L.ID) AND (L.record_key<> C.UPLOADED_ID OR C.UPLOADED_ID IS NULL) AND (C.UPLOADED_ID <> L.ID OR C.UPLOADED_ID IS NULL))
       and c.record_status <> 'DL'
       and c.prohibitautoupdate = 0;

此查询是我想要运行的简化版本,并且需要永久运行(超过3分钟,这是不可接受的)

现在当我运行时:

 SELECT TRIM(l.ID) ID,
       TRIM(C.UID) UID,
       TRIM(c.UPLOADED_ID) UPLOADED_ID,
       TRIM(l.record_key) record_key,
       TRIM(c.customers_record_key) customers_record_key,
       c.prohibitautoupdate,
       TRIM(c.c_additional_key) c_additional_key,
       TRIM(c.record_status) c_record_status    
FROM tmp_customers_upload l, customers c 
WHERE (l.record_key = c.customers_record_key AND NVL(TRIM(l.ID),' ') <> c.UPLOADED_ID AND c.UPLOADED_ID IS NOT NULL )
   and c.record_status <> 'DL'
   and c.prohibitautoupdate = 0;

UNION SELECT TRIM(l.ID) ID,
       TRIM(C.UID) UID,
       TRIM(c.UPLOADED_ID) UPLOADED_ID,
       TRIM(l.record_key) record_key,
       TRIM(c.customers_record_key) customers_record_key,
       c.prohibitautoupdate,
       TRIM(c.c_additional_key) c_additional_key,
       TRIM(c.record_status) c_record_status    
FROM tmp_customers_upload l, customers c
WHERE (SUBSTR(C.UID, 6, 11) = TRIM(L.ID) AND (L.record_key <> C.customers_record_key OR C.customers_record_key IS NULL) AND (C.UPLOADED_ID <> L.ID OR C.UPLOADED_ID IS NULL))
    and c.record_status <> 'DL'
    and c.prohibitautoupdate = 0;

运行不到一秒钟。

据我所知,第一个版本执行隐式JOIN,WHERE子句的行为类似于ON,并且OR以某种方式混淆了DB,使其进行全表扫描。

我的问题是如何优化查询以使其快速运行?我不喜欢使用union,因为正如我所说,这只是查询的简化版本,实际上有30多列,所以使用union会大大降低包含这些查询的SP的可读性和可维护性(实际上是SP中的游标

任何帮助将不胜感激,谢谢

1 个答案:

答案 0 :(得分:0)

问题是因为你没有使用现代风格的连接,你可以看到你的连接条件完全不同。

由于当您尝试将其组合成一个查询时,您的连接条件完全不同,实际上会导致连接条件变为CROSS JOIN(查找它),因此您最终会得到两个表中的多个并且没有能力使用索引。

如果我必须放松这个,我会先切换到现代风格的连接,这样就可以清楚地知道你是如何加入的 - 那么如果你有逻辑问题就会很清楚 - 我想你会这样做。如果逻辑问题被删除,那么组合查询可能是微不足道的。

或不 - 如果逻辑不允许它被组合(因为它们加入不同)并且你必须使用联合。

在这种情况下,最好创建一个由两个查询共享的视图或CTE,以减轻维护问题。