我有这个查询(在oracle中)需要很长时间(15-30秒)( query1 ):
SELECT numcen
FROM centros
WHERE TO_NUMBER (centros.numcen) = TO_NUMBER (?)
OR TO_NUMBER (centros.numcen) IN (
SELECT TO_NUMBER (dc.centro)
FROM datos_centro dc, centros c
WHERE TO_NUMBER (c.numcen) = TO_NUMBER (dc.centro)
AND TO_NUMBER (dc.centro_superior) = TO_NUMBER (?));
我不知道为什么,因为这是一个非常简单的查询。我认为这是因为IN
中的子查询,但是如果我运行这样的子查询( query2 ):
SELECT TO_NUMBER (dc.centro)
FROM datos_centro dc, centros c
WHERE TO_NUMBER (c.numcen) = TO_NUMBER (dc.centro)
AND TO_NUMBER (dc.centro_superior) = TO_NUMBER (?)
只需要100-200ms。
更重要的是,如果我运行 query2 并将其结果放在{em> query1 替换子查询中的IN
内,则结果立即生效。
我无法运行解释计划因为我没有权利。
如果我在mysql下运行(由TO_NUMBER
替换CAST
),情况会更糟。这需要2分钟以上,这是不可接受的。
那么,有没有办法改进第一个查询( query1 )?我应该分成两部分吗?如果我将OR
替换为UNION
(这要快得多),它会是同一个查询吗?
非常欢迎任何建议。谢谢,抱歉我的英语。
答案 0 :(得分:1)
您可以对两个查询做一个解释计划。 解释[你的sql]的计划; select * from table(dbms_xplan.display);
优化器会告诉不同计划之间的差异。
在我看来,第一个查询必须使用嵌套循环并遍历centros中的每一行并评估子查询中的每个记录以将其过滤掉。
第二个查询将在这两个表之间进行散列连接,并执行两次读取然后连接。这工作要少得多。
答案 1 :(得分:0)
你只是尝试使用全局临时表概念,在临时表中插入子qry的结果集,然后使用select * from temp table或直接将它与你的主qry连接。
我相信,即使我有这个问题,这也会使你的表现提高很多倍。
如果你有任何疑问,请试着告诉我。
CREATE GLOBAL TEMPORARY TABLE my_temp_table (
column1 NUMBER) ON COMMIT PRESERVE ROWS;
insert into my_temp_table
SELECT TO_NUMBER (dc.centro)
FROM datos_centro dc, centros c
WHERE TO_NUMBER (c.numcen) = TO_NUMBER (dc.centro)
AND TO_NUMBER (dc.centro_superior) = TO_NUMBER (?)
答案 2 :(得分:0)
在子查询中引用中心是多余的。
尝试:
SELECT numcen
FROM centros
WHERE TO_NUMBER (centros.numcen) = TO_NUMBER (?)
OR TO_NUMBER (centros.numcen) IN (
SELECT TO_NUMBER (dc.centro)
FROM datos_centro dc
AND TO_NUMBER (dc.centro_superior) = TO_NUMBER (?));
......或......
SELECT numcen
FROM centros
WHERE TO_NUMBER (centros.numcen) IN (
SELECT TO_NUMBER (?)
FROM dual
UNION ALL
SELECT TO_NUMBER (dc.centro)
FROM datos_centro dc
AND TO_NUMBER (dc.centro_superior) = TO_NUMBER (?));
如果你不需要那些TO_NUMBER()函数,那么就去除它们,或者在TO_NUMBER(centros.numcen)和TO_NUMBER(dc.centro_superior)上添加基于函数的索引。