목차
由索引引出简单实验几例
【例1】数据量小不需建索引
【例2】全表扫描IO成本低于使用索引情况 
【例3】构造表时集簇因子数分别为接近块数、接近行数
데이터 베이스 MySQL 튜토리얼 “索引”实验小例

“索引”实验小例

Jun 07, 2016 pm 03:59 PM
성명 실험 단순한 색인

由索引引出简单实验几例 ***********************************************声明************************************************ 原创作品,出自 深蓝的blog 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/huangyanlong)。 表述有错误之处

由索引引出简单实验几例

***********************************************声明************************************************

原创作品,出自 “深蓝的blog” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/huangyanlong)。

表述有错误之处,请您留言,不胜感激。

提醒:点击目录,更有助于您的查看。

*****************************************************************************************************

对之前的小例子重新归纳了一下,希望可以帮助对索引有进一步的理解。

【例1】数据量小不需建索引

//如果表的数据量很少,全表扫描和走索引成本相差很小,使用索引是不是就没有必要了。
实验操作:
SQL> SELECT ENAME,JOB,SAL FROM SCOTT.EMP;
//先找到一张小表以作实验,查看表中信息,只有14行

ENAME      JOB          SAL
---------- --------- ------
SMITH      CLERK        800
ALLEN      SALESMAN    1600
WARD       SALESMAN    1250
JONES      MANAGER     2975
MARTIN     SALESMAN    1250
BLAKE      MANAGER     2850
CLARK      MANAGER     2450
SCOTT      ANALYST     3000
KING       PRESIDENT   5000
TURNER     SALESMAN    1500
ADAMS      CLERK       1100
JAMES      CLERK        950
FORD       ANALYST     3000
MILLER     CLERK       1300

已选择14行。
SQL> SET AUTOTRACE ON
SQL> SET AUTOTRACE TRACEONLY
SQL> SELECT * FROM SCOTT.EMP WHERE ENAME='JAMES';
//全表扫描查找JAMES的信息

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    38 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    38 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

SQL> CREATE INDEX IND_EMP_ENAME ON SCOTT.EMP(ENAME);
//为ENAME列建索引
SQL> SELECT * FROM SCOTT.EMP WHERE ENAME='JAMES';
//走列索引查找JAMES的信息
--------------------------------------------------------------------------------


| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |               |     1 |    38 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| EMP           |     1 |    38 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | IND_EMP_ENAME |     1 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------
//全表扫描成本是3%,走索引成本是2%
//从以上实验发现,在表的数据量很小的情况下,全表扫描和走索引成本上相差不大。 
로그인 후 복사

【例2】全表扫描IO成本低于使用索引情况

**************************************************************************
举一个例子,不恰当的使用索引,比用全表扫描的的IO成本更加高。
**************************************************************************
解答:
    思路:创建一组rowid是散落在多个表数据块中的索引,这样由于索引列数据的分布情况和索引中的顺序差异很大,致使通过全表扫表比走索引更能降低IO的使用成本。
操作如下:
SQL> CREATE TABLE TAB_HYL AS SELECT * FROM DBA_OBJECTS;
//创建了一个TAB_HYL表以作实验
SQL> ANALYZE TABLE TAB_HYL COMPUTE STATISTICS;
//分析这张TAB_HYL实验表
SQL> SELECT NUM_ROWS,BLOCKS FROM USER_TABLES WHERE TABLE_NAME ='TAB_HYL';
//查找出实验表上的行数、块数

  NUM_ROWS     BLOCKS
---------- ----------
     72606       1033

SQL> SELECT 72606/1033 FROM DUAL;
//计算平均每个块中的行数为70行

72606/1033
----------
 70.286544

SQL> DROP TABLE TAB_HYL PURGE;
//删除这张表,这张表就是为了计算出每块所占的行数,从而对其进行构建完成实验
SQL> CREATE TABLE TAB_HYL AS SELECT * FROM DBA_OBJECTS WHERE ROWNUM<=70;
//重新创建实验表让它装入70行形成第一个块
SQL> INSERT INTO TAB_HYL SELECT * FROM TAB_HYL;
//复制相同的70行插到实验表中,即实验表中共有140行数据,两个块
SQL> /    
//再次执行相同操作,但此时基准的实验表为140行,因此第三次插入了140行数据,即现在实验表有280行数据
SQL> /    
//按照上面的方法以下连续创建,形成多个块,让每个块中都有相同的键值而形成一组实验用的ROWID
SQL> /
SQL> /
SQL> /
SQL> /
SQL> COMMIT;
SQL> CREATE INDEX IND_H1 ON TAB_HYL(OBJECT_ID);
//创建实验表中OBJECT_ID列的索引,之后通过该列值进行查询,来说明查询的成本
SQL> ANALYZE TABLE TAB_HYL COMPUTE STATISTICS; //分析一下实验表
SQL> SELECT NUM_ROWS,BLOCKS FROM USER_TABLES WHERE TABLE_NAME =&#39;TAB_HYL&#39;;
//查看一下此时实验表的行数、块数已经达到实验准备条件,可以开始试验了

  NUM_ROWS     BLOCKS
---------- ----------
      8960        103

SQL> SET AUTOTRACE ON
SQL> SET AUTOTRACE TRACEONLY  
//设定跟踪
SQL> SELECT * FROM TAB_HYL WHERE OBJECT_ID=70;
//通过上面创建了索引的列来查找,得到下面的分析结果,记住cpu的成本为30,并且数据库自动完成的是走全表扫描,说明数据库已经判断出什么方式查询,成本更低了。

----------------------------------------------------------------------

| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------

|   0 | SELECT STATEMENT  |         |   128 | 10112 |    30   (0)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| TAB_HYL |   128 | 10112 |    30   (0)| 00:00:01 |

----------------------------------------------------------------------
//之后我们人为让查询走索引再看一下分析结果。
SQL> SELECT /*+INDEX(TAB_HYL IND_H1)*/ * FROM TAB_HYL WHERE OBJECT_ID=70;
//强制查询走索引,输出一下结果,看到成本是102,要远高于全表扫描的成本(全表扫描是30,见上表)。

----------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time   
----------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |   128 | 10112 |   102(0)| 00:00:02 |

|   1 |  TABLE ACCESS BY INDEX ROWID| TAB_HYL |   128 | 10112 |   102(0)| 00:00:02 |

|*  2 |   INDEX RANGE SCAN          | IND_H1  |   128 |       |     1(0)| 00:00:01 |
----------------------------------------------------------------------
通过以上实验说明,当索引列数据的分布情况和索引中的顺序差异很大这种情况出现时,做索引范围扫描效率偏低。
로그인 후 복사

【例3】构造表时集簇因子数分别为接近块数、接近行数

**************************************************************************
建两张表,各建一个索引。要求A表的索引集簇因子接近表块数,B表的索引集簇因子接近表行数。
**************************************************************************
(一)、创建A表:索引集簇因子接近表块数
操作:
SQL> CREATE TABLE TAB_HYL AS SELECT * FROM DBA_OBJECTS;
//先创建了一个TAB_HYL表以作实验源表,为了通过这个表分析出表中一个块所占的行数
SQL> ANALYZE TABLE TAB_HYL COMPUTE STATISTICS;
//分析这张TAB_HYL实验表
SQL> SELECT NUM_ROWS,BLOCKS FROM USER_TABLES WHERE TABLE_NAME =&#39;TAB_HYL&#39;;
//查找出实验表上的行数、块数

  NUM_ROWS     BLOCKS
---------- ----------
     72606       1033

SQL> SELECT 72606/1033 FROM DUAL;
//计算平均每个块中的行数为70行

72606/1033
----------
 70.286544

SQL> DROP TABLE TAB_HYL PURGE;
//删除这张表
SQL> CREATE TABLE TAB_HYL AS SELECT * FROM DBA_OBJECTS WHERE ROWNUM<=70;
//重新创建实验表让它装入70行形成第一个块
SQL> INSERT INTO TAB_HYL SELECT * FROM TAB_HYL;
//复制相同的70行插到实验表中,即实验表中共有140行数据,两个块
SQL> /    
//再次执行相同操作,但此时基准的实验表为140行,因此第三次插入了140行数据,即现在实验表有280行数据
SQL> /    
//按照上面的方法以下连续创建,这是为了构造实验表的集簇因子
SQL> /
SQL> /
SQL> /
SQL> /
SQL> COMMIT;
SQL> CREATE TABLE TAB_A AS SELECT * FROM TAB_HYL ORDER BY OBJECT_ID;
//根据实验表创建出表A,表A是通过OBJECT_ID排序的,因此就得到了键值相同的分布较集中的块
SQL> CREATE INDEX IND_H1 ON TAB_A(OBJECT_ID);
//创建A表中OBJECT_ID列的索引
SQL> ANALYZE TABLE TAB_A COMPUTE STATISTICS;
//分析一下A表
SQL> SELECT NUM_ROWS,BLOCKS FROM USER_TABLES WHERE TABLE_NAME = &#39;TAB_A&#39;;

  NUM_ROWS     BLOCKS
---------- ----------
      8960        102

SQL> SELECT BLEVEL,LEAF_BLOCKS,DISTINCT_KEYS,AVG_LEAF_BLOCKS_PER_KEY,CLUSTERING_FACTOR
  2  FROM USER_INDEXES
  3  WHERE INDEX_NAME = &#39;IND_H1&#39;;
//查看A表索引列的b-tree级别、叶的块数、不同的key值、平均每个key所占的叶块的数量、聚集的因子

 BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY CLUSTERING_FACTOR
------- ----------- ------------- -----------------------  -----------------
      1          18            70                       1                102

//得到了A表索引列的集簇因子数(102)与上面的A表的块数(102)是相同的。

(二)、创建B表:索引集簇因子接近表行数
操作:
SQL> CREATE TABLE TAB_HYL AS SELECT * FROM DBA_OBJECTS;//创建了一个实验表以作实验
SQL> ANALYZE TABLE TAB_HYL COMPUTE STATISTICS;//分析这张TAB_HYL实验表
SQL> SELECT NUM_ROWS,BLOCKS FROM USER_TABLES WHERE TABLE_NAME =&#39;TAB_HYL&#39;;//查找出实验表上的行数、块数

  NUM_ROWS     BLOCKS
---------- ----------
     72606       1033

SQL> SELECT 72606/1033 FROM DUAL;//计算平均每个块中的行数为70行

72606/1033
----------
 70.286544

SQL> DROP TABLE TAB_HYL PURGE;//删除这张表
SQL> CREATE TABLE TAB_B AS SELECT * FROM DBA_OBJECTS WHERE ROWNUM<=70;//创建B表让它装入70行形成第一个块
SQL> INSERT INTO TAB_B SELECT * FROM TAB_B;//复制相同的70行插到B表中,即B表中共有140行数据,两个块
SQL> /    //再次执行相同操作,但此时基准的B表为140行,因此第三次插入了140行数据,即现在B表有280行数据
SQL> /    //按照上面的方法以下连续创建,这是为了构造B表的集簇因子
SQL> /
SQL> /
SQL> /
SQL> /
SQL> COMMIT;
SQL> CREATE INDEX IND_H2 ON TAB_B(OBJECT_ID);//创建B表中OBJECT_ID列的索引
SQL> ANALYZE TABLE TAB_B COMPUTE STATISTICS; //分析一下B表
SQL> SELECT NUM_ROWS,BLOCKS FROM USER_TABLES WHERE TABLE_NAME =&#39;TAB_B&#39;;//查看一下此时B表的行数、块数

  NUM_ROWS     BLOCKS
---------- ----------
      8960        103

SQL> SELECT BLEVEL,LEAF_BLOCKS,DISTINCT_KEYS,AVG_LEAF_BLOCKS_PER_KEY,CLUSTERING_FACTOR
  2  FROM USER_INDEXES
  3  WHERE INDEX_NAME = &#39;IND_H2&#39;;

//查看B表索引列的b-tree级别、叶的块数、不同的key值、平均每个key所占的叶块的数量、集簇因子

 BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY  CLUSTERING_FACTOR

------- ----------- ------------- -----------------------  -----------------

      1          18            70                       1               7070

//B表索引列的集簇因子(7070)和B表中的行数(8960)相对接近.           
로그인 후 복사

【例4】有关索引监控

**************************************************************************
对一张表的索引开监控,看是否有使用到。
**************************************************************************
会话A:
SQL> ALTER INDEX IND_H1 MONITORING USAGE;

//对上面练习中用到的IND_H1索引开监控

SQL> SELECT * FROM V$OBJECT_USAGE;

//通过查看V$OBJECT_USAGE视图查看对IND_H1索引的监控信息,MON为YES代表已经开监控了,当前没有人用到

INDEX_NAME          TABLE_NAME             MON USE  START_MONITORING     END_MONITORING
------------------- ---------------------- --- ---  -------------------  -------------------
IND_H1              TAB_A	           YES NO   03/18/2014 16:54:29

会话B:
SQL> SET AUTOTRACE ON;
//开监控,确认下面的操作是走索引的

SQL> SELECT * FROM TAB_A WHERE OBJECT_ID=70;
//使用带索引列查询,分析结果如下
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |   128 | 10112 |     3   (0)| 00:0
0:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| TAB_A  |   128 | 10112 |     3   (0)| 00:0
0:01 |

|*  2 |   INDEX RANGE SCAN          | IND_H1 |   128 |       |     1   (0)| 00:0
0:01 |
--------------------------------------------------------------------------------

会话A:
SQL> SELECT * FROM V$OBJECT_USAGE;

//再次通过V$OBJECT_USAGE视图查看对IND_H1索引的监控信息,MON为YES代表已经开监控了,USE为YES代表当前有人在使用

INDEX_NAME          TABLE_NAME             MON USE  START_MONITORING     END_MONITORING
------------------- ---------------------- --- ---  -------------------  -------------------
IND_H1              TAB_A	           YES YES  03/18/2014 16:54:29
로그인 후 복사

***********************************************声明************************************************

原创作品,出自 “深蓝的blog” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/huangyanlong)。

表述有错误之处,请您留言,不胜感激。

提醒:点击目录,更有助于您的查看。

*****************************************************************************************************

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

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

하드 드라이브 일련 번호를 쿼리하는 가장 쉬운 방법 하드 드라이브 일련 번호를 쿼리하는 가장 쉬운 방법 Feb 26, 2024 pm 02:24 PM

하드디스크 일련번호는 하드디스크의 중요한 식별자로 일반적으로 하드디스크를 고유하게 식별하고 하드웨어를 식별하는 데 사용됩니다. 운영 체제를 설치하거나, ​​올바른 장치 드라이버를 찾거나, 하드 드라이브를 수리할 때와 같이 하드 드라이브 일련 번호를 쿼리해야 하는 경우도 있습니다. 이 문서에서는 하드 드라이브 일련 번호를 확인하는 데 도움이 되는 몇 가지 간단한 방법을 소개합니다. 방법 1: Windows 명령 프롬프트를 사용하여 명령 프롬프트를 엽니다. Windows 시스템에서는 Win+R 키를 누르고 "cmd"를 입력한 후 Enter 키를 눌러 명령을 엽니다.

Java를 사용하여 간단한 학생 성과 보고서 생성기를 작성하는 방법은 무엇입니까? Java를 사용하여 간단한 학생 성과 보고서 생성기를 작성하는 방법은 무엇입니까? Nov 03, 2023 pm 02:57 PM

Java를 사용하여 간단한 학생 성과 보고서 생성기를 작성하는 방법은 무엇입니까? 학생 성과 보고서 생성기는 교사나 교육자가 학생 성과 보고서를 신속하게 생성하는 데 도움이 되는 도구입니다. 이 기사에서는 Java를 사용하여 간단한 학생 성과 보고서 생성기를 작성하는 방법을 소개합니다. 먼저 학생 개체와 학생 성적 개체를 정의해야 합니다. 학생 객체에는 학생의 이름, 학번 등의 기본 정보가 포함되고, 학생 점수 객체에는 학생의 과목 점수, 평균 성적 등의 정보가 포함됩니다. 다음은 간단한 학생 개체의 정의입니다.

Oracle 인덱스 유형은 무엇입니까? Oracle 인덱스 유형은 무엇입니까? Nov 16, 2023 am 09:59 AM

Oracle 인덱스 유형은 다음과 같습니다. 1. B-트리 인덱스, 3. 함수 인덱스, 5. 역방향 키 인덱스, 7. 도메인 인덱스, 비트맵 연결 인덱스 10. 복합 인덱스. 세부 소개: 1. B-트리 인덱스는 동시 작업을 효율적으로 지원할 수 있는 자체 균형 트리 데이터 구조입니다. Oracle 데이터베이스에서 B-트리 인덱스는 가장 일반적으로 사용되는 인덱스 유형입니다. 2. 비트 그래프 인덱스는 인덱스 유형 기반입니다. 비트맵 알고리즘 등에 관한 것입니다.

PHP를 통해 간단한 온라인 예약 시스템을 작성하는 방법 PHP를 통해 간단한 온라인 예약 시스템을 작성하는 방법 Sep 26, 2023 pm 09:55 PM

PHP를 통해 간단한 온라인 예약 시스템 작성 방법 인터넷의 대중화와 사용자의 편의성 추구로 인해 온라인 예약 시스템이 점점 더 대중화되고 있습니다. 레스토랑, 병원, 미용실 또는 기타 서비스 산업이든 간단한 온라인 예약 시스템은 효율성을 높이고 사용자에게 더 나은 서비스 경험을 제공할 수 있습니다. 이 기사에서는 PHP를 사용하여 간단한 온라인 예약 시스템을 작성하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 데이터베이스 및 테이블 생성 먼저 예약 정보를 저장할 데이터베이스를 생성해야 합니다. MyS에서는

C++로 간단한 지뢰 찾기 게임을 작성하는 방법은 무엇입니까? C++로 간단한 지뢰 찾기 게임을 작성하는 방법은 무엇입니까? Nov 02, 2023 am 11:24 AM

C++로 간단한 지뢰 찾기 게임을 작성하는 방법은 무엇입니까? 지뢰 찾기(Minesweeper)는 플레이어가 지뢰를 밟지 않고 알려진 지뢰밭의 배치에 따라 모든 블록을 드러내야 하는 고전적인 퍼즐 게임입니다. 이 기사에서는 C++를 사용하여 간단한 지뢰 찾기 게임을 작성하는 방법을 소개합니다. 먼저 지뢰찾기 게임의 지도를 표현하기 위해 2차원 배열을 정의해야 합니다. 배열의 각 요소는 공개 여부, 지뢰 유무 등 블록의 상태를 저장하는 데 사용되는 구조일 수 있습니다. 또한, 우리는 또한 정의해야

C++로 간단한 음악 추천 시스템을 작성하는 방법은 무엇입니까? C++로 간단한 음악 추천 시스템을 작성하는 방법은 무엇입니까? Nov 03, 2023 pm 06:45 PM

C++로 간단한 음악 추천 시스템을 작성하는 방법은 무엇입니까? 소개: 음악 추천 시스템은 현대 정보 기술의 연구 핫스팟으로 사용자의 음악 선호도와 행동 습관을 기반으로 노래를 추천할 수 있습니다. 이 기사에서는 C++를 사용하여 간단한 음악 추천 시스템을 작성하는 방법을 소개합니다. 1. 사용자 데이터 수집 먼저 사용자의 음악 선호도 데이터를 수집해야 합니다. 다양한 유형의 음악에 대한 사용자의 선호도는 온라인 설문조사, 설문지 등을 통해 얻을 수 있습니다. 텍스트 파일이나 데이터베이스에 데이터 저장

PHP를 사용하여 간단한 파일 관리 기능을 개발하는 방법 PHP를 사용하여 간단한 파일 관리 기능을 개발하는 방법 Sep 20, 2023 pm 01:09 PM

PHP를 사용하여 간단한 파일 관리 기능을 개발하는 방법 소개: 파일 관리 기능은 많은 웹 애플리케이션의 필수 부분입니다. 사용자는 파일을 업로드, 다운로드, 삭제, 표시할 수 있어 사용자에게 편리한 파일 관리 방법을 제공합니다. 이 기사에서는 PHP를 사용하여 간단한 파일 관리 기능을 개발하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. 프로젝트 생성 먼저 기본 PHP 프로젝트를 생성해야 합니다. 프로젝트 디렉토리에 다음 파일을 생성합니다: index.php: 업로드 테이블을 표시하는 데 사용되는 메인 페이지

PHP는 다른 문자열에 있는 문자열의 시작 위치부터 끝 ​​위치까지 문자열을 반환합니다. PHP는 다른 문자열에 있는 문자열의 시작 위치부터 끝 ​​위치까지 문자열을 반환합니다. Mar 21, 2024 am 10:31 AM

이 글은 PHP가 다른 문자열에서 문자열의 시작 위치부터 끝 ​​위치까지 문자열을 반환하는 방법을 자세히 설명합니다. 편집자는 이것이 꽤 실용적이라고 생각하므로 참고용으로 공유하겠습니다. 이 기사에서 뭔가를 얻을 수 있습니다. PHP에서 substr() 함수를 사용하여 문자열에서 부분 문자열을 추출합니다. substr() 함수는 문자열에서 지정된 범위 내의 문자를 추출할 수 있습니다. 구문은 다음과 같습니다. substr(string,start,length) 여기서: string: 하위 문자열을 추출할 원래 문자열입니다. start: 하위 문자열의 시작 위치에 대한 인덱스입니다(0부터 시작). 길이(선택 사항): 하위 문자열의 길이입니다. 지정하지 않은 경우

See all articles