2009-10-16 48 views
3

我最近在阅读关于Oracle索引组织表(IOT)的内容,但我不确定我是否理解何时使用它们。所以我有一个小桌子:是否适合索引组织表?

create table categories 
(
    id  VARCHAR2(36), 
    group  VARCHAR2(100), 
    category VARCHAR2(100 
) 
create unique index (group, category, id) COMPRESS 2; 

id列是从其他表entries一个外键和我常用的查询是:

select e.id, e.time, e.title from entries e, categories c where e.id=c.id AND e.group=? AND c.category=? ORDER by e.time 

条目表正确索引。这两个表都有数百万行(当前16M),目前这个查询真的很臭(注意:我把它换成了分页查询,所以我只返回前20个,但为了简单起见我省略了) 。

因为我基本上索引整个表,所以创建此表作为IOT是否有意义?

编辑大众的需求:

create table entries 
(
    id  VARCHAR2(36), 
    time  TIMESTAMP, 
    group  VARCHAR2(100), 
    title  VARCHAR2(500), 
    .... 
) 

create index (group, time) compress 1; 

我真正的问题我不认为要看这虽然。基本上,如果你有一个有少量列的表(在这个例子中是3个),并且你打算在所有三行上放置一个复合索引,是否有任何理由不使用IOT?

+0

你可以显示条目表+索引吗? – 2009-10-16 20:34:30

+0

完成,表格添加 – Gandalf 2009-10-20 19:37:33

+1

两张表格之间的基数是多少?我有点困惑,因为你声明“两个表都有16M行”。 - 什么是类别表的主键..您提到的唯一索引? - 组和声音与我非常相似..有什么区别? (基本上,我正在寻找如何提高查询性能的方法,不应该影响类别是否是物联网。) – Thorsten 2009-10-22 20:09:56

回答

1

IOT中是非常适合多种用途,包括这种情况下你要对列的所有(或大部分)的指标无论如何 - 但是如果你没有好处只有物化额外的索引 - 这个想法是,表本身就是一个索引,所以按照您希望索引所在的顺序放置这些列。就你而言,你正在通过id访问类别,所以这对于那些成为第一列。所以你有一个索引(id,group,category)。我不知道为什么你想要一个额外的索引(组,类别,ID)。

您的疑问:

SELECT e.id, e.time, e.title 
FROM entries e, categories c 
WHERE e.id=c.id AND e.group=? AND c.category=? 
ORDER by e.time 

你的ID连接表,但你有没有entries.id指数 - 这样的查询可能做一个散列或分类合并连接。我不介意看到你的系统现在正在做的计划来确认。

如果您正在执行分页查询(即只对少量行感兴趣),您希望尽可能快地返回第一行;要做到这一点,你可能会想在条目的嵌套循环,例如:

NESTED LOOPS 
    ACCESS TABLE BY ROWID - ENTRIES 
     INDEX RANGE SCAN - (index on ENTRIES.group,time) 
    ACCESS TABLE BY ROWID - CATEGORIES 
     INDEX RANGE SCAN - (index on CATEGORIES.ID) 

自从加盟,一类是在ID,你要对ID的索引;如果你把它变成物联网,并让ID成为领先专栏,那可能就足够了。

上面显示的计划的执行将取决于有多少行匹配给定的“组”,即平均“组”的选择性如何。

+0

我已经有(ID,时间)在entires表中的综合指数 - 应该满足归并排序吗? – Gandalf 2009-10-19 15:47:38

+0

第二次看,我认为我们没有足够的信息。你可以发布你的条目表结构吗?此外,如何选择是e.group和c.category? – 2009-10-20 08:23:49

+0

做 - 添加其他表 – Gandalf 2009-10-20 19:36:43

0

物联网是一个权衡。您获得访问性能以降低插入/更新性能。我们通常将它们用于批量加载的参考数据,并且在白天不更新。这并不是说它是使用它们的唯一方式,而是我们如何使用它们。

很少有东西在这里:

  1. 你提到分页 - 您曾经考虑过FIRST_ROWS提示?
  2. 这就是你的索引所在的顺序,作为第一个字段的组?如果是这样,我会考虑将ID作为第一列,因为该索引不会被使用。
  3. 外键在列上应该有一个索引。考虑添加一个外键索引(id列)。
  4. 你确定它不是ORDER BY导致慢度?
+0

为什么不使用索引?我认为即使索引中的第一列不在查询中,Oracle也会执行使用索引的跳过扫描(自9i起)。是插入性能更糟,然后是具有相同索引的普通表? – Gandalf 2009-10-17 16:47:28

+0

你是对的我其实忘了跳过扫描。它仍然没有那么快,性能就是你想要改进的。 – David 2009-10-17 23:27:10

+0

索引的使用部分取决于其集群因素 - 在某些情况下,执行全表扫描比对索引执行范围扫描要快,特别是在范围相对较大的情况下。跳过扫描会让事情变得更糟 - 如果第一列有大量不同的值,则跳过扫描变得非常昂贵,并且可能很快比FTS变得更加昂贵。 – 2009-10-24 05:09:06

0

您使用的是哪个版本的Oracle? 我假设有一个关于字段ID的表项的主键,是否正确? 为什么WHERE条件不包含“c.group = instancesroup”?

尝试:

  1. 的条件
  2. 变化从 “创建唯一索引(组 类,ID)”,以“创建唯一索引的索引定义(ID,组,类别中删除订单)”
  3. 重新组织表的类别作为IOT上(组,类别ID)
  4. 重新组织表的类别作为IOT上(ID,组,类别)

在上面的每个案例中使用EXPLAIN PLAN来审查成本