Oracle:使用全扫描而不是复合索引

标签 oracle indexing

我有奇怪的 Oracle 优化器行为:

SELECT a.id,
       a.date_insert,
       a.message#cnt
  FROM T_MESSAGE_TRANSMIT A,
       T_LIST l 
 WHERE a.priority_id = 0 
   AND a.status = 'Q'
   and l.id = a.list_id

此查询会对 T_MESSAGE_TRANSMIT 生成全扫描,无论它是覆盖 priority_idstatus 字段的索引:

CREATE BITMAP INDEX INFORMER.IX$MESSAGE_TRANSMIT$6 ON INFORMER.T_MESSAGE_TRANSMIT (STATUS, PRIORITY_ID)

表大小约为 28M 行,7 天前已对其进行了分析(自那天起仅添加了数千行)。

如果我使用提示 /*+index(a IX$MESSAGE_TRANSMIT$6) */ 那么一切都会变得很好,如果我删除连接并将查询重写为:

SELECT a.id,
       a.date_insert,
       a.message#cnt
  FROM T_MESSAGE_TRANSMIT A,
 WHERE a.priority_id = 0 
   AND a.status = 'Q'

哪里可能会出错?

UPD:

问题出在这个优化器设置中:

optimizer_mode  first_rows_10

最佳答案

符合优先级 ID/状态标准的行比例是多少?

例如,如果 20% 的行匹配,则必须在 20% 的情况下访问该行才能获取额外的详细信息。如果它访问 20% 的行,那么它可能会访问 80-90% 的 block 。在这种情况下,忽略索引是正确的。

但是,如果它在没有连接的情况下使用索引进行查询,则更有可能是由于 a.list_id 值所致。如果它使用 BITMAP 索引,则对于它在那里找到的每一行,它必须通过 id 访问 T_LIST 表。如果 T_LIST 很大并且 id 没有索引,那么这可能意味着重复完整扫描 T_LIST 不是一个好主意。

在这种情况下,它可能会从 T_MESSAGE_TRANSMIT 获取所有匹配的行,按 ID 对它们进行排序,然后从 T_LIST 获取匹配的行。与 T_LIST 的哈希连接也可能是合适的。

另外,你确定你不想简单地做一个

SELECT a.id,
       a.date_insert,
       a.message#cnt
  FROM T_MESSAGE_TRANSMIT A
 WHERE a.priority_id = 0 
   AND a.status = 'Q'
   AND a.list_id in (select l.id from T_LIST l)

如果 T_LIST 上的 ID 不唯一,您的原始 SQL 将生成重复项。

关于Oracle:使用全扫描而不是复合索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4778546/

相关文章:

sql - 如何在间隔中添加分钟和秒

Oracle 10g数据库日期转换为 'yyyy-iw'有问题吗?

python - 如何使用元组数组查询 pandas DataFrame?

postgresql - PostGIS,索引相交生成的地理

Mysql Order by 子句使用 "FileSort"

java - 如何将.jar库添加到android studio项目1.2.2?

java - CLOB : JdbcTemplate : c3p0 - how reuse the same connection?

oracle - PLS-00103 : Encountered the symbol “end-of-file” when expecting one of the following: begin function pragma procedure

python - 在工作日范围内扩展索引

mysql - 在 MySQL 中,当我的 where 子句中有 in "in"条件时,我可以使用索引吗?