>  기사  >  데이터 베이스  >  Oracle에는 어떤 인덱스가 있습니까?

Oracle에는 어떤 인덱스가 있습니까?

青灯夜游
青灯夜游원래의
2022-04-18 17:18:098235검색

오라클의 인덱스 유형에는 고유하지 않은 인덱스, 고유 인덱스, 비트맵 인덱스, 로컬 접두어 파티션 인덱스, 로컬 비접두어 파티션 인덱스, 글로벌 접두어 파티션 인덱스, 해시 파티션 인덱스 및 함수 기반 인덱스가 포함됩니다. 테이블에 데이터를 삽입한 후 인덱스를 생성해야 합니다. "create Unique index" 문을 사용하여 고유 인덱스를 생성할 수 있습니다.

Oracle에는 어떤 인덱스가 있습니까?

이 튜토리얼의 운영 환경: Windows 7 시스템, Oracle 11g 버전, Dell G3 컴퓨터.

인덱스란 무엇인가요?

  • 인덱스는 테이블의 데이터에 대한 액세스 속도를 높이기 위해 테이블의 하나 이상의 열에 구축된 보조 개체입니다.
  • Oracle 스토리지 인덱스의 데이터 구조는 B* 트리(균형 트리)입니다. ), 비트맵 인덱스 마찬가지지만 리프 노드는 서로 다른 B* 번호 인덱스를 갖습니다.
  • 인덱스는 루트 노드, 가지 노드 및 리프 노드로 구성됩니다. 상위 레벨 인덱스 블록에는 하위 노드의 인덱스 데이터가 포함됩니다. -레벨 인덱스 블록, 리프 노드에는 인덱스 데이터가 포함되어 있으며 행 ID의 실제 위치를 결정합니다.

색인 설명

1) 색인은 책의 색인과 유사하게 데이터 검색 속도를 높이는 데 사용되는 데이터베이스 개체 중 하나입니다. 데이터베이스에서 색인을 생성하면 데이터베이스 프로그램이 결과를 쿼리할 때 읽어야 하는 데이터의 양을 줄일 수 있습니다. 이는 책에서 책 전체를 읽지 않고도 원하는 정보를 찾기 위해 색인을 사용할 수 있는 방법과 유사합니다.

2) 인덱스는 테이블에 구축된 선택적 개체입니다. 인덱스의 키는 기본 전체 테이블 스캔 검색 방법을 정렬된 인덱스 키 집합으로 대체하여 검색 효율성을 향상시키는 것입니다.

3) 인덱스는 논리적으로나 물리적으로, 관련 테이블 및 데이터와는 아무런 관련이 없습니다. 인덱스를 생성하거나 삭제할 때 기본 테이블에는 영향을 미치지 않습니다.

4) 인덱스가 설정되면 테이블에 대한 DML 작업(예: 삽입, 수정)을 수행할 때; 또는 삭제) 관련 작업 중에 Oracle은 자동으로 인덱스를 관리하며 인덱스 삭제는 테이블에 영향을 미치지 않습니다.

5) 인덱스는 테이블에 인덱스가 있는지 여부에 관계없이 사용자에게 투명합니다.

6) Oracle 생성 기본 키가 사용될 때 이 열에 인덱스가 자동으로 생성됩니다.

인덱스 사용 목적:

  • 질의 속도 향상
  • I/O 작업 감소
  • 디스크 정렬 제거(인덱스는 정렬 속도를 높일 수 있음)

인덱스 사용 시기:

  • 쿼리에서 반환된 레코드 수는 정렬된 테이블의 경우
  • 테이블이 더 조각화되어 있음(자주 추가 및 삭제)

인덱스 유형

  • 고유하지 않은 인덱스(가장 일반적으로 사용됨)
  • 고유 인덱스
  • 비트맵 인덱스
  • 로컬 프리픽스 파티션 인덱스
  • 로컬 프리픽스 파티션 인덱스
  • 글로벌 프리픽스 파티션 인덱스
  • 해시 파티션 인덱스
  • 함수 기반 인덱스

인덱스 관리 지침

  • 다음 이후에 인덱스 생성 테이블에 데이터 삽입
  • SQL*Loader 또는 import 도구를 사용하여 데이터 삽입 또는 로드 마지막으로 인덱싱이 더 효과적입니다. import工具插入或装载数据后,建立索引比较有效;

索引正确的表和列

  • 经常检索排序大表中40%或非排序表7%的行,建议建索引;
  • 为了改善多表关联,索引列用于联结;
  • 列中的值相对比较唯一;
  • 取值范围(大:B*树索引,小:位图索引);
  • Date型列一般适合基于函数的索引;
  • 列中有许多空值,不适合建立索引

为性能而安排索引列

  • 经常一起使用多个字段检索记录,组合索引比单索引更有效;
  • 把最常用的列放在最前面,例:dx_groupid_serv_id(groupid,serv_id),在where条件中使用groupidgroupid,serv_id,查询将使用索引,若仅用到serv_id

올바른 테이블과 열을 인덱싱하세요.

자주 대규모 정렬 테이블에서 행의 40% 또는 정렬되지 않은 테이블에서 7%를 검색하는 경우 인덱스를 구축하는 것이 좋습니다.

    여러 테이블 연결을 개선하려면 인덱스 열이 조인에 사용됩니다.
  • 값 범위(큰: B* 트리 인덱스, 작은: 비트맵 인덱스)

  • 날짜 유형 열은 일반적으로 함수 기반 인덱스에 적합합니다.
  • 인덱싱에 적합하지 않은 열

성능을 위해 인덱스 열 배열

  • 여러 필드를 함께 사용하여 레코드를 검색하는 경우가 많으며, 단일 인덱스보다 결합된 인덱스가 더 효율적입니다.

  • 가장 일반적으로 사용되는 항목을 넣습니다. 열은 앞에 배치됩니다(예: dx_groupid_serv_id(groupid,serv_id)). where 조건에서 groupid 또는 groupid를 사용하세요. serv_id, 쿼리는 인덱스를 사용합니다. serv_id 필드만 사용하면 인덱스가 유효하지 않습니다.
  • 불필요한 인덱스를 병합/분할합니다.
  • 테이블당 인덱스 수를 제한하세요

테이블에는 수백 개의 인덱스가 있을 수 있지만(이렇게 하시겠습니까?) 테이블에 자주 삽입하고 업데이트하는 경우 시스템 CPU에 인덱스가 많아지면 I/ O 부담이 클수록 🎜🎜🎜🎜 각 테이블에는 5개 이하의 인덱스가 있는 것이 좋습니다. 🎜🎜🎜🎜🎜더 이상 필요하지 않은 인덱스 삭제🎜🎜🎜🎜🎜잘못된 인덱스. 주로 B* 트리 인덱스 대신 함수 기반 인덱스 또는 비트맵 인덱스를 사용하기 때문입니다. 🎜🎜🎜🎜애플리케이션의 쿼리가 유효하지 않습니다. 인덱스 사용 🎜🎜🎜🎜인덱스를 재구축하기 전에 인덱스를 삭제해야 합니다. 인덱스를 재구축하기 위해 alter index...rebuild를 사용하는 경우에는 인덱스를 삭제할 필요가 없습니다. 🎜🎜🎜🎜🎜인덱스 데이터 블록 공간 사용량🎜🎜
  • 인덱스를 생성할 때, 특히 기본 키를 생성할 때 테이블 공간을 지정하세요.
  • pctfress를 합리적으로 설정하세요. 참고: 인덱스에 대해 pctused를 지정할 수 없습니다. 그리고 스토리지 매개변수를 합리적으로 설정합니다. 기본값은 테이블스페이스 크기이거나 초기 및 다음 크기가 동일한 크기로 설정됩니다.
병렬로 인덱스 생성을 고려하세요

병렬 인덱스 생성은 대규모 테이블에 사용할 수 있습니다. 인덱스를 병렬로 생성하는 경우 저장 매개변수는 각 쿼리 서버 프로세스에서 별도로 사용됩니다. 예: initial1M이고 병렬 처리는 8이며 인덱스 생성 중에 최소 8M 공간이 소비됩니다.
  • initial1M,并行度为8,则创建索引期间至少要消耗8M空间;

考虑用nologging创建索引

  • 对大表创建索引可以使用nologging来减少重做日志;
  • 节省重做日志文件的空间;
  • 缩短创建索引的时间;
  • 改善了并行创建大索引时的性能。

怎样建立最佳索引?

明确地创建索引

create index index_name on table_name(field_name)
  tablespace tablespace_name
  pctfree 5
  initrans 2
  maxtrans 255
  storage
  (
  minextents 1
  maxextents 16382
  pctincrease 0
  );

创建基于函数的索引:

常用与UPPER、LOWER、TO_CHAR(date)等函数分类上,例:

create index idx_func on emp (UPPER(ename)) tablespace tablespace_name;

创建位图索引:

对基数较小,且基数相对稳定的列建立索引时,首先应该考虑位图索引,例:

create bitmap index idx_bitm on class (classno) tablespace tablespace_name;

明确地创建唯一索引

可以用create unique index语句来创建唯一索引,例:

create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;

创建与约束相关的索引

可以用using index字句,为与uniqueprimary key约束相关的字段创建索引,例如:

alter table table_name
  add constraint PK_primary_keyname primary key (field_name)
  using index tablespace tablespace_name;

如何创建局部分区索引

  • 基础表必须是分区表;
  • 分区数量与基础表相同;
  • 每个索引分区的子分区数量与相应的基础表分区相同;
  • 基础表的子分区中的行的索引项,被存储在该索引的相应的子分区中,例如:
  Create Index TG_CDR04_SERV_ID_IDX On TG_CDR04(SERV_ID)
  Pctfree 5  Tablespace TBS_AK01_IDX
  Storage (
  MaxExtents 32768  PctIncrease 0  FreeLists 1  FreeList Groups 1  )
  local  /

如何创建范围分区的全局索引

基础表可以是全局表和分区表。

create index idx_start_date on tg_cdr01(start_date)
  global partition by range(start_date)
  (partition p01_idx vlaues less than (‘0106’)
  partition p01_idx vlaues less than (‘0111’)
  …
  partition p01_idx vlaues less than (‘0401’ ))
  /

  重建现存的索引
  重建现存的索引的当前时刻不会影响查询;

  重建索引可以删除额外的数据块;
  提高索引查询效率;

alter index idx_name rebuild nologging;

  对于分区索引:

alter index idx_name rebuild partition partiton_name nologging;

要删除索引的原因

  • 不再需要的索引;
  • 索引没有针对其相关的表所发布的查询提供所期望的性能改善;
  • 应用没有用该索引来查询数据;
  • 该索引无效,必须在重建之前删除该索引;
  • 该索引已经变的太碎了,必须在重建之前删除该索引;
  • 语句:<br> drop index idx_name; <br> drop index idx_name drop partition partition_name; <br>

建立索引的代价

基础表维护时,系统要同时维护索引,不合理的索引将严重影响系统资源,主要表现在CPU和I/O上;

插入、更新、删除数据产生大量db file sequential read锁等待;

一个表中有几百万条数据,对某个字段加了索引,但是查询时性能并没有什么提高,这主要可能是oracle的索引限制造成的。

oracle的索引有一些索引限制,在这些索引限制发生的情况下,即使已经加了索引,oracle还是会执行一次全表扫描,查询的性能不会比不加索引有所提高,反而可能由于数据库维护索引的系统开销造成性能更差。

扩展知识:常见的索引限制问题

1、使用不等于操作符(a8093152e673feb7aba1828c43532094, !=)

下面这种情况,即使在列dept_id有一个索引,查询语句仍然执行一次全表扫描

select * from dept where staff_num <> 1000;

但是开发中的确需要这样的查询,难道没有解决问题的办法了吗?

有!

通过把用 or 语法替代不等号进行查询,就可以使用索引,以避免全表扫描:上面的语句改成下面这样的,就可以使用索引了。

select * from dept shere staff_num < 1000 or dept_id > 1000;

2、使用 is null 或 is not null

使用 is nullis nuo null也会限制索引的使用,因为数据库并没有定义null值。如果被索引的列中有很多null,就不会使用这个索引(除非索引是一个位图索引,关于位图索引,会在以后的blog文章里做详细解释)。在sql语句中使用null会造成很多麻烦。

解决这个问题的办法就是:建表时把需要索引的列定义为非空(not null)

3、使用函数

如果没有使用基于函数的索引,那么where

nologging인덱스 생성🎜🎜🎜🎜nologging을 사용하면 대규모 테이블에 대한 인덱스를 생성할 때 리두 로그를 줄일 수 있습니다. 🎜🎜리두 로그 파일의 공간을 절약하고 🎜🎜인덱스 생성 시간을 단축합니다. 큰 인덱스를 병렬로 생성할 때. 🎜🎜🎜최고의 색인을 만드는 방법🎜🎜명시적으로 색인 만들기🎜
select * from staff where trunc(birthdate) = &#39;01-MAY-82&#39;;
🎜함수 기반 색인 만들기:🎜🎜 일반적으로 UPPER, LOWER, TO_CHAR(date) 및 기타 함수와 함께 사용됩니다. 예: 🎜
select * from staff where birthdate < (to_date(&#39;01-MAY-82&#39;) + 0.9999);
🎜비트맵 인덱스 생성:🎜🎜베이스가 작고 상대적으로 안정적인 열에 대한 인덱스를 생성할 때 기본, 첫 번째 비트맵 인덱스를 고려해야 합니다. 예: 🎜
select * from dept where dept_id = 900198;
🎜 명시적으로 고유 인덱스 생성 🎜🎜 create Unique index 문을 사용하여 고유 인덱스를 생성할 수 있습니다. 예: 🎜
select * from dept where dept_id = &#39;900198&#39;;
🎜 Create 제약 조건과 관련된 인덱스 🎜🎜 using index 절을 사용하여 고유기본 키와 관련된 필드에 대한 인덱스를 생성할 수 있습니다. 제약 조건은 다음과 같습니다. 🎜
Column1 like ‘aaa%’ 是可以的
Column1 like ‘%aaa%’用不到
🎜로컬 파티션 인덱스를 만드는 방법🎜 🎜🎜기본 테이블은 분할된 테이블이어야 합니다. 🎜🎜파티션 수는 기본 테이블과 동일합니다. 🎜🎜각 인덱스의 하위 파티션 수 파티션은 해당 기본 테이블 파티션과 동일합니다. 🎜🎜기본 테이블의 하위 파티션에 있는 행의 인덱스 항목은 인덱스의 해당 하위 파티션에 저장됩니다. 예: 🎜🎜
select count(*) from person_info where xb in (select xb_id from dic_sex);

Select count(*) from n_acntbasic a where shbxdjm =:a and exists(select 1 from person_info where pid=a.pid and …);

Select * from person_info where zjhm=3101….;--将会对person_info全表扫描

Select * from person_info where zjhm =‘3101…’;--才能用到索引
🎜만드는 방법 범위 분할 글로벌 인덱스🎜🎜기본 테이블은 글로벌 테이블과 분할 테이블이 될 수 있습니다. 🎜
Select * from test where to_char(dt,’yyyymmdd’) =‘20041010’;
🎜 기존 인덱스 재구축은 현재 쿼리에 영향을 미치지 않습니다. 🎜🎜 인덱스를 재구축하면 추가 데이터 블록이 삭제될 수 있습니다.
인덱스 쿼리 효율성이 향상됩니다. 인덱스: 🎜
select * from test where dt >=to_date(‘20041010’,’yyyymmdd’) and dt < to_date(‘20041010’,’yyyymmdd’) + 1
🎜인덱스 삭제 이유🎜🎜🎜인덱스가 더 이상 필요하지 않습니다. 🎜🎜인덱스가 관련 테이블에서 실행한 쿼리에 대해 예상되는 성능 향상을 제공하지 않습니다. 🎜🎜애플리케이션이 인덱스를 사용하여 쿼리하지 않습니다. data;🎜🎜 인덱스가 잘못되었으므로 다시 작성하기 전에 삭제해야 합니다. 🎜🎜인덱스가 너무 조각화되어 다시 작성하기 전에 인덱스를 삭제해야 합니다. 🎜🎜Statement: <br> drop index idx_name; > drop index idx_name drop partition partition_name <br>🎜🎜🎜인덱싱 비용🎜🎜Basic 테이블 유지 관리 중에 시스템은 인덱스를 동시에 유지해야 합니다. 비합리적인 인덱스는 주로 CPU 및 I/O의 시스템 리소스에 심각한 영향을 미칩니다. 🎜🎜데이터 삽입, 업데이트 및 삭제는 많은 양의 db 파일을 생성합니다. 순차 읽기 잠금 대기 🎜🎜테이블에 수백만 개의 데이터가 있고 특정 필드에 인덱스가 추가되었지만 쿼리 성능이 향상되지 않은 것은 주로 인덱스 제한 때문일 수 있습니다. 오라클. 🎜🎜oracle의 인덱스에는 몇 가지 인덱스 제한이 있습니다. 이러한 인덱스 제한이 발생하면 인덱스가 추가되었더라도 oracle는 여전히 전체 테이블 스캔 및 쿼리를 수행합니다. 인덱스를 추가하지 않는 것에 비해 성능이 향상되지는 않지만, 데이터베이스에 인덱스를 유지하는 시스템 오버헤드로 인해 성능이 저하될 수 있습니다. 🎜🎜확장된 지식: 일반적인 색인 제한 문제🎜🎜1 부등식 연산자(a8093152e673feb7aba1828c43532094, !=)🎜🎜다음 상황에서는 dept_id 컬럼에 인덱스가 있어도 쿼리문은 여전히 ​​전체 테이블 스캔을 수행합니다🎜
Order byGroup byDistinctIn
🎜그런 쿼리가 꼭 필요합니다 개발 중에 문제에 대한 해결책은 없나요? 🎜🎜그렇습니다! 🎜🎜쿼리 시 부등호를 or 구문으로 대체하면 인덱스를 사용하여 전체 테이블 스캔을 피할 수 있습니다. 위의 구문을 다음과 같이 변경하면 인덱스를 사용할 수 있습니다. 🎜rrreee🎜2. is null 또는 is not null🎜🎜 is null 또는 is nuo null을 사용하면 인덱스 사용도 제한됩니다. 데이터베이스가 null 값을 정의하지 않기 때문입니다. 인덱스된 열에 Null이 많으면 인덱스가 사용되지 않습니다(인덱스가 비트맵 인덱스인 경우는 제외). 자세한 내용은 향후 블로그 기사에서 설명합니다. SQL 문에서 null을 사용하면 많은 문제가 발생합니다. 🎜🎜이 문제를 해결하는 방법은 테이블을 생성할 때 인덱스가 필요한 열을 null이 아닌 (null이 아님)🎜🎜함수 사용으로 정의하는 것입니다. >🎜🎜함수 기반 인덱스를 사용하지 않는 경우 인덱스가 있는 열의 where 절에 함수를 사용하면 최적화 프로그램이 이러한 인덱스를 무시하게 됩니다. 다음 쿼리는 인덱스를 사용하지 않습니다: 🎜
select * from staff where trunc(birthdate) = &#39;01-MAY-82&#39;;

但是把函数应用在条件上,索引是可以生效的,把上面的语句改成下面的语句,就可以通过索引进行查找。

select * from staff where birthdate < (to_date(&#39;01-MAY-82&#39;) + 0.9999);

4、比较不匹配的数据类型

比较不匹配的数据类型也是难于发现的性能问题之一。下面的例子中,dept_id是一个varchar2型的字段,在这个字段上有索引,但是下面的语句会执行全表扫描。

select * from dept where dept_id = 900198;

这是因为oracle会自动把where子句转换成to_number(dept_id)=900198,就是3所说的情况,这样就限制了索引的使用。把SQL语句改为如下形式就可以使用索引

select * from dept where dept_id = &#39;900198&#39;;

5、使用like子句

使用like子句查询时,数据需要把所有的记录都遍历来进行判断,索引不能发挥作用,这种情况也要尽量避免。

Like 的字符串中第一个字符如果是‘%’则用不到索引

Column1 like ‘aaa%’ 是可以的
Column1 like ‘%aaa%’用不到

6、使用IN

尽管In写法要比exists简单一些,exists一般来说性能要比In要高的多 

In还是用Exists的时机 

当in的集合比较小的时候,或者用Exists无法用到选择性高的索引的时候,用In要好,否则就要用Exists
例:

select count(*) from person_info where xb in (select xb_id from dic_sex);

Select count(*) from n_acntbasic a where shbxdjm =:a and exists(select 1 from person_info where pid=a.pid and …);

Select * from person_info where zjhm=3101….;--将会对person_info全表扫描

Select * from person_info where zjhm =‘3101…’;--才能用到索引

假定TEST表的dt字段是date类型的并且对dt建了索引。
如果要查‘20041010’一天的数据.下面的方法用不到索引

Select * from test where to_char(dt,’yyyymmdd’) =‘20041010’;

而以下将会用到索引。

select * from test where dt >=to_date(‘20041010’,’yyyymmdd’) and dt < to_date(‘20041010’,’yyyymmdd’) + 1

7、如果能不用到排序,则尽量避免排序。

用到排序的情况有
集合操作。Union ,minus ,intersect等,注:union all 是不排序的。

Order byGroup byDistinctIn

有时候也会用到排序
确实要排序的时候也尽量要排序小数据量,尽量让排序在内存中执行,有文章说,内存排序的速度是硬盘排序的1万倍。

在排序的字段上创建索引,让排序在内存中执行,加快排序速度。

8、在基于CBO的优化器(花费)下,表的统计数据过期。也可能导致不使用索引。

解决:执行表分析。获取表的最新信息。

9、获取的数据量过大,全部扫描效率更高

10、索引字段的值分散率太低,值太集中,如类型字段都是1,2, 状态类型Y-有效/N-无效。这类型的字段最好别建索引。

尽管在这些字段上建立了索引,但对全表数据区分度不大。最后还是会全表扫描。

推荐教程:《Oracle教程

위 내용은 Oracle에는 어떤 인덱스가 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.