1

我们有一个系统,我们有一个项目集合(> 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. 所以我们需要一些方法来对itemsand的连接做一个否定索引itemsProcessed(我们已经在 mongo 上完成了这个,但是 oracle 似乎不能做类似的事情)

甲骨文有可能吗?

4

3 回答 3

1

您可以尝试向您的查询添加/*+ first_rows */提示

SELECT /*+ first_rows (10) */... FROM items i ...

或尝试先选择未处理的项目,然后再选择<additional queries on items>

with i_to_process AS
(
  SELECT item  FROM items
  minus 
  SELECT item FROM itemsProcessed WHERE processor IN (1, 2)
)
select * from i_to_process
where 
<additional queries on items>
于 2016-09-28T12:55:14.110 回答
0

根据表的更新频率,您可以创建 itemsNotProcessed 的物化视图。处理将提前完成。您还可以进行一些非规范化并将已处理标志添加到项目表并在标志上添加位图索引。

于 2016-10-07T20:43:12.140 回答
0

IMO 这是一个设计问题。当您应该尝试包含尚未处理的项目时,您正在尝试排除已处理的项目。已处理的项目列表将不断增长;要处理的项目列表将保持较小。与其拥有已处理的项目表(itemsProcessed),我建议您创建一个要处理的项目表,然后将其内部连接到查询中,在处理项目时从 ITEMS_TO_BE_PROCESSED 表中删除项目。

祝你好运。

于 2016-09-28T11:32:24.410 回答