【发布时间】:2017-02-06 08:08:54
【问题描述】:
我们有一个系统,我们有一个项目集合(> 100 万个),还有几个处理它的东西。每个处理器应该只处理每个项目一次,并且处理器有一个层次结构。
我们当前的实现是有一个“已处理”表来跟踪每个处理器已经完成的工作:
CREATE TABLE items (id NUMBER PRIMARY KEY, ...)
CREATE TABLE itemsProcessed(
item NUMBER REFERENCES items(id),
processor NUMBER)
我们的查询是这样的(itemsProcessed 上面有相关索引) - 我们使用 NOT IN 来过滤掉当前处理器或其祖先已经处理过的项目:
SELECT ... FROM items i WHERE <additional queries on items>
AND id NOT IN (SELECT item FROM itemsProcessed WHERE processor IN (1, 2))
当处理的表变得非常大时,这个查询开始需要很长时间(几秒钟),因为它必须在开始返回第一项之前进行大量过滤(查询计划使用哈希反连接)
我们需要此查询以非常快速地返回前几项 - 理想情况下返回 500 毫秒以下的前几项。这意味着它不能遍历items 并过滤掉itemsProcessed 中的那些。所以我们需要在items 和itemsProcessed 的连接上做一个否定索引(我们已经在mongo上完成了这个,但是oracle似乎不能做类似的事情)
Oracle 可以做到这一点吗?
【问题讨论】:
-
如果这样能得到更好的结果,你能试试吗?
AND id IN (SELECT item FROM itemsProcessed WHERE processor > 2)。如果您的processor永远不是NULL,它应该返回相同的结果,但没有NOT表达,这在某些情况下可能会更好地使用索引 -
你的外键是否被索引 - 你说你有一个“相关”索引,还是你只索引
processor?它们是什么类型的索引?执行计划显示什么?您是否尝试过使用not exists代替?如果您只想要前几行未处理的行,则使用rownum停止键? -
查询所用的时间,还取决于您在
中所做的事情。你在表上使用索引吗? -
所有其他 WHERE 子句都被索引,oracle 正在使用索引进行过滤。需要时间的是通过大量已处理项目的反连接搅动
-
@AlexPoole rownum 过滤器没有帮助 - 它必须在返回任何东西之前检查许多已经处理的项目,这就是需要时间的原因
标签: oracle query-performance notin anti-join