在 order by 子句的情况下,Oracle 不在 varchar2 列上使用索引

Oracle doesn't use index on varchar2 column in case of of order by clause

这是我的 table 数百万行:

  CREATE TABLE "TEST_TABLE"
  ( "ID" NUMBER(*,0),
    "TYPE" NUMBER(*,0),
    "NAME" VARCHAR2(10 BYTE)
  );

和几个索引:

   CREATE INDEX TEST_INDEX_T_N ON TEST_TABLE (TYPE, NAME);
   CREATE INDEX TEST_INDEX_T_I ON TEST_TABLE (TYPE, ID);

如果是以下查询

   SELECT * FROM TEST_TABLE WHERE TYPE = 1 ORDER BY ID

我得到了以下计划

   |   0 | SELECT STATEMENT |                |   886K|    21M|  2192   (1)| 00:00:27 |
   |*  1 |  INDEX RANGE SCAN| TEST_INDEX_T_I |   886K|    21M|  2192   (1)| 00:00:27 |

但是,在以下情况下:

   SELECT NAME FROM TEST_TABLE WHERE TYPE = 1 ORDER BY NAME;

我得到了

   |   0 | SELECT STATEMENT  |                |   886K|    16M|       |  7826   (1)| 00:01:34 |
   |   1 |  SORT ORDER BY    |                |   886K|    16M|    23M|  7826   (1)| 00:01:34 |
   |*  2 |   INDEX RANGE SCAN| TEST_INDEX_T_N |   886K|    16M|       |  2415   (1)| 00:00:29 |

因此,据我所知,oracle 不使用索引对 varchar 列进行排序(因为在解释计划中有额外的 SORT ORDER BY 操作),但是对于 INT 或 DATE 类型,一切都很好。 "use index for sorting" varchar 列怎么可能?

如果您的 TYPE 的不同值很少,那么优化器可能会计算出只执行 table 的完整扫描并对结果进行排序比读取高比例的 table 通过索引。

Oracle 可以使用索引为字符列提供有序排序,但您还必须考虑 ORDER BY 是二进制的(即根据 ASCII 或其他字符代码)还是语言的(因语言而异) ).您可能必须使用与 NLS 语言排序顺序匹配的特定 NLS 参数创建索引,或者修改 ORDER BY 以使其基于文本的二进制代码。

您应该采取的方法取决于您是否为文本使用 ASCII 以外的字符集,甚至可能您是否关心正确排序大写和小写字符。

也许当您执行 ORDER BY NAME 时,实际顺序可能因您当地的 NLS_SORTNLS_COMP 设置而异。因此,索引中的顺序可能与输出的顺序不同。在任何 DATENUMBER 数据类型的情况下,订单 ASCDESC 总是 相同并且很可能是与内部组织索引相同。