我有一个问题,我想在查询中添加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中的游标
任何帮助将不胜感激,谢谢
答案 0 :(得分:0)
问题是因为你没有使用现代风格的连接,你可以看到你的连接条件完全不同。
由于当您尝试将其组合成一个查询时,您的连接条件完全不同,实际上会导致连接条件变为CROSS JOIN(查找它),因此您最终会得到两个表中的多个并且没有能力使用索引。
如果我必须放松这个,我会先切换到现代风格的连接,这样就可以清楚地知道你是如何加入的 - 那么如果你有逻辑问题就会很清楚 - 我想你会这样做。如果逻辑问题被删除,那么组合查询可能是微不足道的。
或不 - 如果逻辑不允许它被组合(因为它们加入不同)并且你必须使用联合。
在这种情况下,最好创建一个由两个查询共享的视图或CTE,以减轻维护问题。