我有一个Oracle SQL查询作为存储过程的一部分:
DELETE FROM item i
WHERE NOT EXISTS (SELECT 1 FROM item_queue q WHERE q.n=i.n)
AND NOT EXISTS (SELECT 1 FROM tool_queue t WHERE t.n=i.n);
关于表格的一点:
我想知道查询/子查询是否可以某种方式进行优化以使它们运行得更快,我认为删除通常相当快
答案 0 :(得分:4)
将您的删除变为选择,然后您可以检查并优化查询部分。
否则请注意 - 删除不是最快的事情。删除时会发生很多事情。
OTOH我认真思考....问题是两个子查询。查询计划是什么样的?答案 1 :(得分:3)
尝试类似:
DELETE FROM item WHERE n NOT IN
(SELECT i.n FROM item i INNER JOIN item_queue q ON i.n = q.n
UNION SELECT i.n FROM item i INNER JOIN tool_queue t ON i.n = t.n)
您的相关子查询在您的示例中分别运行了10K次。此技术将运行两个INNER JOIN查询以获取要删除的“n”列表。
您可能需要稍微调整一下SQL;我不熟悉Oracle方言。
答案 2 :(得分:1)
请尝试避免在您的Quires中进行Subselect并改为使用INNER JOIN
答案 3 :(得分:1)
确保对引用项表的大型表没有约束。在删除的情况下,这可能是一个真正的减速。
答案 4 :(得分:1)
如果不做额外的工作,你无法真正得到一个好的答案。
在SQL语句iteself之后,最重要的是对象的统计信息(本例中的表和索引)具有代表性。
然后你真的需要查看oracle选择的访问路径 - 许多方法都可以做到这一点。
尝试
EXPLAIN PLAN SET STATEMENT_IS = 'SQL01' FOR
DELETE FROM item i
WHERE NOT EXISTS (SELECT 1 FROM item_queue q WHERE q.n=i.n)
AND NOT EXISTS (SELECT 1 FROM tool_queue t WHERE t.n=i.n);
然后
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
也许在这里发布结果。
当您尝试不同的事情 - 例如重写查询,修改索引等时,您会注意到访问路径发生了变化。
这是一个相当复杂的领域 - 你需要学习/练习。
由于多种原因,删除速度很慢,但一个重要因素是维护表上的索引。但是,在您的情况下,您说只有10k行非常小。 (顺便说一下,你没有在这里给出时间。目前是花了1,10或100秒?你想要达到什么目标?)所以我会专注于通过更大的桌子的访问路径。
我的第一种方法可能是:
DELETE FROM item i
WHERE NOT EXISTS
(SELECT NULL
FROM item_queue q,
tool_queue g
where q.key = g.key -- if the tables are related
AND q.n=i.n) ;
但正如我所说,这里有很多因素。
答案 5 :(得分:0)
尝试使用SELECT而不是delete来查看DELETE操作真正的瓶颈
答案 6 :(得分:0)
虽然它可能不会更快,但如果你这样做会更容易阅读:
DELETE FROM item i
WHERE n NOT IN (SELECT n FROM item_queue)
AND n NOT IN (SELECT n FROM tool_queue)