【问题标题】:Is an Index Organized Table appropriate here?索引组织表在这里合适吗?
【发布时间】:2023-03-09 14:45:01
【问题描述】:

我最近在阅读有关 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 

条目表已正确编入索引。

这两个表都有数百万行(目前为 1600 万行),目前这个查询真的很糟糕(注意:我也将它包装在分页查询中,所以我只取回前 20 行,但为简单起见,我省略了)。

既然我基本上是在索引整个表,那么将这个表创建为 IOT 是否有意义?

编辑应大众需求:

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

create index (group, time) compress 1;

我认为我真正的问题并不取决于此。基本上,如果您有一个包含少量列的表(本例中为 3 列)并且您计划在所有三行上放置一个复合索引,是否有任何理由不使用 IOT?

【问题讨论】:

  • 可以显示条目表+索引吗?
  • 两张表之间的基数是多少?我对您声明“两个表都有 16M 行”这一事实感到有些困惑。 - 类别表的主键是什么......你提到的唯一索引? - 组和类别听起来和我很相似.. 有什么区别? (基本上,我正在寻找有关如何提高查询性能的方法,无论类别是否为 IOT,都不应受到影响。)
  • 所以条目是分组存储的,一个条目可以有多个类别。所以实际上如果条目有 1600 万行,那么理论上类别可以有更多。组和类别彼此无关。

标签: oracle indexing


【解决方案1】:

IOT 非常适合多种用途,包括这种情况下,无论如何您都将在所有(或大部分)列上建立索引 - 但只有在您没有 em> 额外的索引 - 这个想法是表本身就是一个索引,因此将列按照您希望索引所在的顺序排列。在您的情况下,您通过 id 访问类别,因此对于这是第一列。如此有效地,您已经获得了(id、group、category)的索引。我不知道您为什么要在 (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 连接表,但 entry.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)

由于与 CATEGORIES 的连接是在 ID 上的,因此您需要一个 ID 上的索引;如果您将其设为 IOT,并将 ID 设为前导列,则可能就足够了。

我上面显示的计划的性能将取决于有多少行与给定的“组”匹配 - 即平均“组”的选择性。

【讨论】:

  • 我已经在 (id, time) 的整个表上有一个复合索引 - 应该满足 SORT MERGE 吧?
  • 再看一遍,我认为我们没有足够的信息。您可以发布条目表的结构吗?另外,e.group 和 c.category 的选择性如何?
  • 我把你误入歧途了 Jeff - id 是那个表的 PK,所以它确实有一个索引(我忽略了一个)。 (id, group) 是条目表的唯一PK。
【解决方案2】:

你看过dba-oracle.com、asktom.com、IOUG、another asktom.com吗?

物联网需要支付罚款 - 例如,插入性能较差

你能制作原型并比较性能吗?

另外,也许您可​​能想考虑hash cluster。

【讨论】:

    【解决方案3】:

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

    这里有几件事:

    1. 您提到了分页 - 您是否考虑过 first_rows 提示?
    2. 这是您的索引的顺序,组作为第一个字段吗?如果是这样,我会考虑将 ID 移动为第一列,因为不会使用该索引。
    3. 外键应该在列上有一个索引。考虑在外键(id 列)上添加索引。
    4. 您确定不是 ORDER BY 导致缓慢吗?

    【讨论】:

    • 为什么不使用索引?我认为 Oracle 会执行使用索引的跳过扫描(从 9i 开始),即使索引中的第一列不在查询中。插入性能比同索引的普通表差吗?
    • 你说得对,我实际上忘记了跳过扫描。它仍然没有那么快,性能是您想要改进的地方。
    • 索引的使用部分取决于它的聚集因子——在某些情况下,对索引执行全表扫描比对索引执行范围扫描更快,尤其是在范围相对较大的情况下。跳过扫描的情况会变得更糟 - 如果第一列有大量不同的值,跳过扫描会变得非常昂贵,并且很快就会变得比 FTS 更昂贵。
    【解决方案4】:

    您使用的是什么版本的 Oracle? 我假设字段 id 的表条目上有一个主键,对吗? 为什么 WHERE 条件不包含 "c.group = e.group" ?

    尝试:

    1. 按条件删除订单
    2. 从“创建唯一索引(组, category, id)”到“创建唯一索引(id, group, category)”
    3. 将表类别重新组织为(组、类别、id)上的 IOT
    4. 将表类别重新组织为(id、组、类别)上的 IOT

    在上述每种情况下,请使用EXPLAIN PLAN 来查看费用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多