【问题标题】:oracle query is not using indexesoracle 查询没有使用索引
【发布时间】:2014-05-30 11:13:38
【问题描述】:

我是 Oracle 的新手,虽然我已经相当广泛地使用 SQL Server,但我不需要深入研究数据库设计的细节……特别是索引。因此,我花了很多时间阅读有关索引的教程......无论是概念上的还是特定于 Oracle 的。

为了将我的理解付诸实践,我设置了一个非常简单的表,其中包含一些基本索引。

CREATE TABLE "SYSTEM"."TBL_PERSON" 
   (    
        "PERSON_ID" NUMBER(10,0) NOT NULL ENABLE, 
        "FIRST_NAME" NVARCHAR2(120) NOT NULL ENABLE, 
        "MIDDLE_NAME" NVARCHAR2(120), 
        "LAST_NAME" NVARCHAR2(120) NOT NULL ENABLE, 
        "DOB" DATE NOT NULL ENABLE, 
        "IS_MALE" NCHAR(1) DEFAULT 'T' NOT NULL ENABLE,
        CONSTRAINT "TBL_PERSON_PK" PRIMARY KEY ("PERSON_ID")
   )

如您所见,PERSON_ID 字段包含表中每条记录的唯一 ROWID,并且是一个自动递增的主键。

(请不要挂断缺少的 SQL,除非它与 INDEXES 不起作用的问题有关。我试图从 DDL 中仅选择相关的 SQL,并且可能遗漏了一些项目。那里有很多东西我认为与此问题无关,因此我尝试将其删除)

我在表上创建了几个额外的非聚集索引。

CREATE INDEX "SYSTEM"."IDX_LAST_NAME" ON "SYSTEM"."TBL_PERSON" ("LAST_NAME") 
CREATE INDEX "SYSTEM"."IDX_PERSON_NAME" ON "SYSTEM"."TBL_PERSON" ("FIRST_NAME", "LAST_NAME")

当我在以下 SQL 上运行“解释计划”时,我收到通知说 PK 索引已按预期使用。

select * from TBL_PERSON where PERSON_ID = 21

但是,当我运行查询以选择具有特定 LAST_NAME 的人时,LAST_NAME 索引似乎被忽略了。

select * from TBL_PERSON where LAST_NAME = 'Stenstrom'

为什么不使用 IDX_LAST_NAME?对于它的价值,我对复合索引 IDX_PERSON_NAME 有同样的问题。

【问题讨论】:

  • 与您当前的问题没有直接关系,但有些事情可以让您更轻松地过渡到 Oracle... 永远不要在 SYSSYSTEM 架构中创建自己的对象,为你的对象。 SYSSYSTEM 由 Oracle 保留,功能有时在此处的行为会有所不同。 ROWID 是 Oracle 中的保留字,指的是行的物理地址,而不是主键值。在新开发中很少会想要使用NVARCHAR2 数据类型,选择Unicode 字符集并改用VARCHAR2
  • 此外,Oracle 没有聚集索引之类的东西,因此将索引称为“非聚集”只会造成混淆。 Oracle 中最接近聚集索引的是索引组织表——如果您谈论“非聚集索引”,人们可能会认为您有一个索引组织表,而不是您实际创建的堆组织表.
  • tbl_person 包含多少行? LAST_NAME上的查询返回了多少?
  • @a_horse_with_no_name (America! nice:) ) - 我已将记录增加到大约 25 条以上。在此特定查询中,将返回 8 条记录。
  • 对于 25 行中的 8 行,使用索引没有意义。这 25 行可能都驻留在同一个数据库块上,这意味着全表扫描只是一次 I/O 操作——最多 2 次。对较大表的索引扫描通常仅在查询返回不超过约 0 时才有效。总行数的 10-15%。

标签: sql oracle indexing


【解决方案1】:

您问题的关键是“基数”列。您估计只有五行为该表返回。

Oracle 有两种执行计划可供选择:

  1. 加载数据页。扫描数据页上的五条记录,选择符合条件的一条。
  2. 加载索引并扫描它以查找匹配项。然后加载数据页面并查找匹配的记录。

Oracle 得出的结论是,对于 5 条记录,第一种方法更快。如果您将更多数据加载到表中,您应该会看到执行计划发生了变化。或者,如果您使用的是 select last_name 而不是 select *,那么 Oracle 可能会选择索引。

【讨论】:

  • +1 但值得注意的是,基数5并不是Oracle对表中总行数的估计,而是对过滤后返回的行数的估计。
  • @jonearles 。 . .谢谢你的澄清。
  • 参与索引大约需要多少条记录?数百、数千等?我现在有 25 个,但仍然没有使用索引……而且我的家庭成员快用完了!!哈哈
  • 我在“解释计划”中添加了 2020 更多行和索引 - 谢谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-05
相关资源
最近更新 更多