2010-03-16 55 views
2

我有一个Oracle SQL查询作为存储过程的一部分: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); 

有关台A位:

  • 项目包含有大约10K行在n列索引
  • item_queue含有约1mil的行也具有索引n个列
  • tool_queue含有约5密耳的行索引以及

我想知道,如果查询/子查询可以以某种方式优化,使其运行速度更快,我想删除普遍较快

+1

请重新格式化您的代码,以便它不是在滚动窗格。 – Timothy 2010-03-16 16:03:26

回答

0

尝试使用SELECT而不是删除看到的是DELETE操作,真正的瓶颈

4

将您的删除转为选择,然后您可以检查和优化查询部分。

否则注意 - 删除不是最快的事情。很多事情发生在删除。

OTOH我认真思考....问题是两个子查询。查询计划是什么样的?

1

尽量避免子选择在您奎雷斯和使用INNER JOIN代替

+0

除INNER JOIN不起作用外。如果你在'item'和'item_queue'和'tool_queue'之间进行内部连接,你会得到你不想删除的'item'的一个子集。 – 2010-03-16 16:13:04

+0

不是内部连接比select语句更昂贵吗?如果我错了,请纠正我。 – suprasad 2010-03-16 16:46:54

+0

@Shannon Severance黄金法则“两次TIME select一次删除” @ sprasad12让有人白衣更多的经验纠正我,但我作为我知道,作为子选择和函数的事情慢得多,然后在查询中加入 – adopilot 2010-03-16 17:17:45

0

虽然它可能没有任何更快它会更容易,如果你没有阅读:

DELETE FROM item i 
WHERE n NOT IN (SELECT n FROM item_queue) 
AND n NOT IN (SELECT n FROM tool_queue) 
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方言。

+0

语法应罚款为Oracle,但我认为你需要使用'或',而不是'和',因为这既**不存在原来的检查**。另外,使用** excplicit连接**会使其更具可读性。 – 2010-03-16 16:16:43

+0

谢谢彼得,你是对的。我编辑了答案,将两个查询和UNION结果集分开,避免了进入凌乱的多表JOIN;我重新格式化为使用INNER JOIN语法(尽管对于像我这样的老人来说,他们同样可读)。 – 2010-03-16 16:27:39

+0

@Larry勒斯蒂格:我同意他们同样可读在这种情况下,但我怀疑有人可以够老发现使用几十一些*真正*条件同样可读;-) – 2010-03-16 16:34:44

1

请确保您对引用项目表的大型表没有约束。在删除的情况下,这可能会真正放缓。

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) ; 

但是就像我说这里有很多因素。