索引使用简介

一、 关于索引的知识

要写出运行效率高的sql,需要对索引的机制有一定了解,下面对索引的基本知识做一介绍。

1、 索引的优点和局限

索引可以提高查询的效率,但会降低dml操作的效率。

所以建立索引时需要权衡。对于dml操作比较频繁的表,索引的个数不宜太多。

2、 什么样的列需要建索引?

经常用于查询、排序和分组的列(即经常在where、order或group by子句中出现的列)。

3、 主键索引和复合索引

对于一张表的主键,系统会自动为其建立索引。

如果一张表的几列经常同时作为查询条件,可为其建立复合索引。

4、 建立索引的语句

create index i_staff on staff (empno);

create index i_agent on agent (empno, start_date);

5、 删除索引的语句

drop index I_staff;

drop index I_agent;

6、 查询索引的语句 法一:利用数据字典

表一:all_indexes 查看一张表有哪些索引以及索引状态是否有效

主要字段: index_name, table_name, status

例如:select index_name, status

from all_indexes

where table_name=’STAFF_INFO’;

INDEX_NAME STATUS

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

I_STAFF VALID

表二:all_ind_columns 查看一张表在哪些字段上建了索引

主要字段: table_name, index_name, column_name, column_position

例如: select index_name, column_name, column_position

from all_ind_columns

where table_name=’AGENT’

INDEX_NAME COLUMN_NAME COLUMN_POSITON

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

I_AGENT EMPNO 1

I_AGENT START_DATE 2

由此可见,agent表中有一个复合索引(empno, start_date )

法二:利用toad工具

toad用户界面比sql*plus友好,并且功能强大。你可以在toad编辑器中键入表名,按F4,便可见到这张表的表结构以及所有索引列等基本信息。

7、 索引的一些特点

1): 不同值较多的列上可建立检索,不同值少的列上则不要建。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就没必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。

2): 如果在索引列上加表达式,则索引不能正常使用

例如:b1,c1分别是表b,c的索引列

select * from b where b1/30<1000;

select * from c where to_char(c1,’YYYYMMDD HH24:MI:SS’)= ‘20020314:01:01’;

以上都是不正确的写法

3): where子句中如果使用in、or、like、!=,均会导致索引不能正常使用例如:select * from b where b1=30or b1=40;4): 使用复合索引进行查询时必须使用前置列

例如表a上有一个复合索引(c1,c2,c3),则c1为其前置列

如果用c1或c1+c2或c1+c2+c3为条件进行查询,则该复合索引可以发挥作用,反之,用c2或c3或c2+c3进行查询,则该索引不能起作用。

二. 书写sql注意事项:

1、 避免给sql语句中引用的索引列添加表达式:

典型实例:

b1,c1分别是表b,c的索引列:

1) select * from b where b1/30< 1000 ;

2) select * from c where to_char(c1,’YYYYMMDD HH24:MI:SS’)= ‘20020314:01:01’;

替代方案:

1) select * from b where b1 < 30000;

2) select * from c where c1= to_date(‘2002030114:01:01’, ‘YYYYMMDD HH24:MI:SS’);

注:在lbs中有两个重要字段,pol_info中的undwrt_date和prem_info中的payment_date,这两个日期是带时分秒的,所以经常有同事用to_char 来查询某一时间段的数据。

例如:select count(*) from pol_info where to_char(undwrt_date,’YYYYMMDD’)=’20020416’;select count(*) from prem_info where to_char(undwrt_date,’YYYYMM’)=’200203’;替代方案:

select count(*) from pol_info

where undwrt_date>=to_date(’20020416’,’YYYYMMDD’) and

undwrt_date select count(*) from prem_info

where payment_date>=to_date(’20020301’,’YYYYMMDD’) and

payment_date

2、 避免在where子句中使用in、or、like、!=

典型实例:

a1是a表上的索引列:

1) select * from a

where ( a1 = ‘0’ and ...) or (a1 = ‘1’ and ...);

2) select count(*) from a where a1 in (‘0’,’1’) ;

替代方案:

1) select * from a where a1 = ‘0’ and ...

union

select * from a where a1 = ‘1’ and ...

2) select count(*) from a where a1 = ‘0’;

select count(*) from a where a1 = ‘1’;

然后做一次加法运算;或者直接用存储过程来实现;

小结:

对字段使用了 ‘in,or,like’ 做条件、对字段使用了不等号 ‘!=’,均会使索引失效;如果不产生大量重复值,可以考虑把子句拆开;拆开的子句中应该包含索引,或者使用union连结符代替。另一种方式是使用存储过程,它使SQL变得更加灵活和高效。

3、 建立适当的索引

曾经接过开发的一个统计sql, select … from tablea where cola=… and …

运行效率非常慢,经查tablea数据量巨大,再查all_ind_columns,发现cola是tablea的一个复合索引中的一列,但不是前置列。象这种情况,就需要与开发商量,是否针对cola建一个索引。

4、 like和substr

对于‘like’和‘substr’,其效率并没有多大分别。但是,当所搜索的值不存在时,使用‘like’的速度明显大于‘substr’。

所以:select * from a where substr(a1,1,4) = '5378' 可以用like替代

select * from a where a1 like ‘5378%’;

5、 写where条件时,有索引字段的判断在前,其它字段的判断在后;如果where条件中用到复合索引,按照索引列在复合索引中出现的顺序来依次写where条件;

6、使用多表连接时,在from子句中,将记录数少的表放在后面,可提高执行效率;

7、避免使用not in

not in 是效率极低的写法,尽量使用minus或外连接加以替代

典型实例:

1) select col1 from tab1 where col1 not in (select col1 from tab2);

2) select sum(col2) from tab1 where col1 not in (select col1 from tab2);

替代方案

select col1 from tab1 minus select col1 from tab2;

select sum(a.col2) from tab1 a, tab2 b

where a.col1=b.col2(+) and b.col1 is null;

8、多表查询时,如果其中一个表的记录数量明显大于其他表,则可以先对此表进行查询后,再与其他小表进行表连接。

典型实例:

select a.plan_code, b.dno, c,tno, sum(a.tot_modal_prem),

from prem_info a, dept_ref b, plan_type c

where substr(a.deptno,1,7) = substr(b.deptno,1,7)

and a.plan_code = c.plan_code

group by b.dno, c.tno, a.plan_code;

替代方案:

select b.dno, c.tno, a.plan_code, a.tot_amount

from (select plan_code, deptno, sum(tot_modal_prem) tot_amount

from prem_info

group by deptno, plan_code) a

dept_ref b,

plan_type c

where substr(a.deptno,1,7) = substr(b.deptno,1,7)

and a.plan_code = c.plan_code

group by b.dno, c.tno, a.plan_code;

小结:

由于prem_info表的记录数远远大于dept_ref表和plan_type表中的记录数, 所以首先从prem_info表中查询需要的记录,此时记录数已经被大量缩小,然后再和其他两个表连接,速度会得到很大改善!

9、查询数量较大时,使用表连接代替IN,EXISTS,NOT IN,NOT EXISTS等。

典型实例:

a、使用IN:

select sum(col2) from tab1 where col1 in (select col1 from tab2);

使用EXISTS::

select sum(col2) from tab1 a

where exists ( select * from tab2 where col1=a.col1);

b、使用NOT IN:

select sum(col2) from tab1 where col1 not in (select col1 from tab2);

使用NOT EXISTS:

select sum(col2) from tab1 a

where not exists ( select * from tab2 where col1=a.col1);

替代方案:

a、使用连接:

select sum(a.col2) from tab1 a,tab2 b where a.col1=b.col2;

b、使用外连接:

select sum(a.col2) from tab1 a,tab2 b

where a.col1=b.col2(+) and b.col1 is null;

\•索引是建立在表的一列或多个列上的辅助对象,它有利于快速访问表的数据。

•索引由于其内在的结构,它具有某些内在的开销,这些开销依赖于为了检索由索引中ROWID指定的行所访问的表中的块数,并且这个开销可能会超过进行全表扫描的成本。

聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。

聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行的一个查询经常检索某一日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的行,直到到达结束日期。这样有助于提高此类查询的性能。同样,如果对从表中检索的数据进行排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行排序,从而节省成本。

当索引值唯一时,使用聚集索引查找特定的行也很有效率。例如,使用唯一雇员 ID 列 emp_id 查找特定雇员的最快速的方法,是在 emp_id 列上创建聚集索引或 PRIMARY KEY 约束。

非聚集索引与聚集索引一样有 B 树结构,但是有两个重大差别:

数据行不按非聚集索引键的顺序排序和存储。非聚集索引的叶层不包含数据页。 相反,叶节点包含索引行。每个索引行包含非聚集键值以及一个或多个行定位器,这些行定位器指向有该键值的数据行(如果索引不唯一,则可能是多行)。 非聚集索引可以在有聚集索引的表、堆集或索引视图上定义。在 Microsoft®SQL Server™ 2000 中,非聚集索引中的行定位器有两种形式:

如果表是堆集(没有聚集索引),行定位器就是指向行的指针。该指针用文件标识符 (ID)、页码和页上的行数生成。整个指针称为行 ID。如果表没有聚集索引,或者索引在索引视图上,则行定位器就是行的聚集索引键。如果聚集索引不是唯一的索引,SQL Server 2000 将添加在内部生成的值以使重复的键唯一。用户看不到这个值,它用于使非聚集索引内的键唯一。SQL Server 通过使用聚集索引键搜索聚集索引来检索数据行,而聚集索引键存储在非聚集索引的叶行内。 由于非聚集索引将聚集索引键作为其行指针存储,因此使聚集索引键尽可能小很重要。如果表还有非聚集索引,请不要选择大的列作为聚集索引的键。

关于索引(转)

索引的三個問題

索引( Index )是常见的数Database 的性能。虽然有许多,还是有不少的人对它存在误解Oracle 8.1.7 OPS on HP N se使用不同的方法后,数据的比较明白事情的关键。 据库对象,它的设置好坏、使用是否资料讲索引的用法, DBA 和 Develo,因此针对使用中的常见问题,讲三ries ,示例全部是真实数据,读者不。本文所讲基本都是陈词滥调,但是 得当,极大地影响数据库应用程序和per 们也经常与它打交道,但笔者发现个问题。此文所有示例所用的数据库是需要注意具体的数据大小,而应注意在笔者试图通过实际的例子,来真正让您

第一讲、索引并非总是最佳选择

如果发现Oracle 在有索引,Oracle 确实会选择全表扫描 的情况下,没有使用索引,这并不是(Full Table Scan),而非索引扫描 Oracle 的优化器出错。在有些情况下(Index Scan)。这些情况通常有:

1. 表未做statistics, 或 者 statistics 陈旧,导致 Oracle 判断失误。

2. 根据该表拥有的记录数和数据块数,实际上全表扫描要比索引扫描更快。

对第1种情况,最常见的例子,是以下这句sql 语句:

select count(*) from mytable;

在未作statistics 之前,它使用全表扫描,statistics 之后,使用的是 INDEX (FAST FULL S得不好,也会导致Oracle 不使用索引。 需要读取6000多个数据块(一个数据块是8k), 做了CAN) ,只需要读取450个数据块。但是,statistics 做

第2种情况就要复杂得多。一般概念上都认为扫描快。为了讲清楚这个问题,这里先介绍一下Or:CF(Clustering factor) 和 FF(Filtering fact 索引比表快,比较难以理解什么情况下全表扫描要比索引acle 在评估使用索引的代价(cost)时两个重要的数据or).

CF: 所谓 CF, 通俗地讲,就是每读入一个索引块,要对应读入多少个数据块。

FF: 所谓 FF, 就是该sql 语句所选择的结果集,占总的数据量的百分比。

大约的计算公式是:FF * (要读入的数据块块数。需要读入全表扫描需要读入的数据块数等 CF + 索引块个数) ,由此估计出,的数据块越多,则 cost 越大,Orac于该表的实际数据块数) 一个查询, 如果使用某个索引,会需le 也就越可能不选择使用 index. (

其核心就是, CF 可能会比实际的数据块数量建立时,索引中的记录与表中的记录有良好的对应对应关系越来越乱,CF 也越来越大。此时需要 DB 大。CF 受到索引中数据的排列方式影响,通常在索引刚关系,CF 都很小;在表经过大量的插入、修改后,这种A 重新建立或者组织该索引。

如果某个sql 语句以前一直重新整理该索引了。 使用某索引,较长时间后不再使用, 一种可能就是 CF 已经变得太大,需要

FF 则是Oracle 根据 stati,最大值是409654,考虑以下sq stics 所做的估计。比如, mytablesl 语句: 表有32万行,其主键myid的最小值是1

Select * from mytables where myid>=1; 和

Select * from mytables where myid>=400000

这两句看似差不多的 sql 者的 FF 可能只有 1%。如果它实际上,在我们的数据库上的测 语句,对Oracle 而言,却有巨大的的CF 大于实际的数据块数,则Oracl试验证了我们的预测. 以下是在HP 差别。因为前者的 FF 是100%, 而后e 可能会选择完全不同的优化方式。而

第二讲、索引也有好坏

索引有 B tree 索引, Bit全称是Balanced , 其意义是,有一个字段(Single column),Function-based index. 许多de map 索引, Reverse b tree 索引,从 tree 的 root 到任何一个leaf 也可以有多个字段(Composite),veloper 都倾向于使用单列B 树索引 等。最常用的是 B tree 索引。 B 的,要经过同样多的 level. 索引可以只最多32个字段,8I 还支持 。

所谓索引的好坏是指:

1,索引不是越多越好。特别是大量从来或者个索引即会降低性能,而且在一个sql 中, Oracl 几乎不用的索引,对系统只有损害。OLTP系统每表超过5e 从不能使用超过 5个索引。

2,很多时候,单列索引不如复合索引有效率。

3,用于多表连结的字段,加上索引会很有作用。

那么,在什么情况下单列索所查询的列,全部都出现在复合使用多个单列索引要快得多。( 引不如复合索引有效率呢?有一种情索引中时,此时由于 Oracle 只需要此时,这种优化方式被称为 Index o 况是显而易见的,那就是,当sql 语句查询索引块即可获得所有数据,当然比nly access path)

第三讲、索引再好,不用也是白搭

抛开前面所说的,假设你设不用,那么,需要做的第一件事 置了一个非常好的索引,任何傻瓜都情,是审视你的 sql 语句。 知道应该使用它,但是Oracle 却偏偏

Oracle 要使用一个索引,有一些最基本的条件:

1, where 子句中的这个字段,必须是复合索引的第一个字段;

2, where 子句中的这个字段,不应该参与任何形式的计算

具体来讲,假设一个索引是按 f1, f2, f3的= : var2, 则因为 f2 不是索引的第1个字段,无 次序建立的,现在有一个 sql 语句, where 子句是 f2 法使用该索引。

第2个问题,则在我们之中非常严重。以下是从 实际系统上面抓到的几个例子:

Select jobid from mytabs where isReq='0' and to_date (updatedate) >= to_Date ( '2001-7-18', 'YYYY-MM-DD');

以上的例子能很容易地进行和 内存资源。 改进。请注意这样的语句每天都在我 们的系统中运行,消耗我们有限的cpu

除了1,2这两个我们必须牢记于心的原则外,。这里我只讲哪些操作或者操作符会显式(explic 还应尽量熟悉各种操作符对 Oracle 是否使用索引的影响itly)地阻止 Oracle 使用索引。以下是一些基本规则:

1, 如果 f1 和 f2 是同一个表的两个字段,则 f1>f2, f1>=f2, f1

2, f1 is null, f1 is no t null, f1 not in, f1 !=, f1 lik e ‘%pattern%’;

3, Not exist

4, 某些情况下,f1 in 也会不用索引;

对于这些操作,别无办法,许可以将 in 操作改成 比较操 只有尽量避免。比如,如果发现你的作 + union all。笔者在实践中发现 sql 中的 in 操作没有使用索引,也很多时候这很有效。

但是,Oracle 是否真正使用索引,使用索引,对所写的复杂的 sql, 在将它写入应用程序之前Oracle 对该 sql 的解析(plan),可以明确地看是否真正有效,还是必须进行实地的测验。合理的做法是,先在产品数据库上做一次explain . explain 会获得到 Oracle 是如何优化该 sql 的。

如果经常做 explain, 就会划往往不尽如人意。事实上,将然这已经是题外话了。发现,喜爱写复杂的 sql 并不是个复杂的 sql 拆开,有时候会极大地好习惯,因为过分复杂的sql 其解析计提高效率,因为能获得很好的优化。当没有对name建索引之前,oracle使用全表扫描。时间长短视数据库参数db_file_multiblock_read_count的设置,一次读取db_file_multiblock_read_count*db_block_size(db_cache_dize)的数据.

建立索引之后,oracle使用index range scan,一次读取一条索引。

mysql查询一个表有哪些索引_如何查看某张数据库表上都有哪些索引(转)相关推荐

  1. mysql查询学生平均成绩及其名次_数据库面试题:数据库查询语句

    Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 问题 ...

  2. MySQL查询一个表的前25%的数据

    MySQL查询一个表的前25%的数据,SQL如下: # qianfeng SELECT g.* FROM (SELECT @rownum:=0) r join tb_shopping_car g wh ...

  3. 如何设计一张数据库表

    如何设计一张数据库表 1.前言 ​  如何设计一张数据库表,或者说设计一张数据库表需要注意些什么,这是我最近在思考的问题,刚开始,我简单的罗列了一下注意事项: 设置合理的主键: 根据字段更改的频率程度 ...

  4. 【唠叨两句】如何将一张树型结构的Excel表格中的数据导入到多张数据库表中...

    小弟昨天遇到一个相对比较棘手的问题,就像标题说的那样.如何将一张树型结构的Excel表格中的数据导入到多张数据库表中,在现实中实际是七张数据库表,这七张表之间有着有着相对比较复杂的主外键关系,对于我这 ...

  5. mysql 查询相同字段值的个数_好文 | MySQL 索引B+树原理,以及建索引的几大原则...

    MySQL事实上使用不同的存储引擎也是有很大区别的,下面猿友们可以了解一下. 一.存储引擎的比较 注:上面提到的B树索引并没有指出是B-Tree和B+Tree索引,但是B-树和B+树的定义是有区别的. ...

  6. mysql查询到最新记录就停止_使用Limit参数优化MySQL查询 在找到一个记录后将停止查询...

    优化 MySQL 查询的 Limit 参数 我们在做一些查询的时候总希望能避免数据库引擎做全表扫描,因为全表扫描时间长,而且其中大部分扫描对客户端而言是没有意义的.那么在 MySQL 中有那些方式是可 ...

  7. mysql查询一个字段最大值_查询表中某一个字段的数字最大值的记录

    这个是一个csdn上有人问的一个题目,具体的题目如下: 数据库表 表1 id name 1 DB-235-aa-fc 2 DB-275-ag-fw 3 DB-235-ajj-fj 4 DB-44444 ...

  8. mysql 查询一个字段快还是一条记录快_mysql (优化)查询一条再筛选某个字段和直接查询该条的某个字段的效率比较...

    查询所有,10000次, $sql = "select * from mh_user where (username='333') and (password='xxx')"; 总 ...

  9. mysql 删除一个字段语句怎么写_删除的sql语句怎么写

    1. 删除一个表的sql 语句怎么写啊 使用drop语句,drop table (需要删除表的名字). drop是删除整个表,delete是删除表的内容. drop语句的作用:删除内容和定义,释放空间 ...

最新文章

  1. Udacity机器人软件工程师课程笔记(十四)-运动学-正向运动学和反向运动学(其一)
  2. Ubuntu基础知识
  3. SAP plant and location
  4. 错误:docker-ce-cli conflicts with 2:docker-1.13.1-103.git7f2769b.el7.centos.x86_64 错误:docker-ce confli
  5. D - 又见回文---C11新标准
  6. Java二叉搜索树转循环链表,关于java:二叉搜索树转换为单向链表interview1712
  7. 转载浅谈MFC内存泄露检测及内存越界访问保护机制
  8. 称重问题 —— 哪个是假币?
  9. rk3399_android7.1添加个驱动且加上宏控编译
  10. 采用DIV+CSS布局的好处
  11. 坚果pro2刷回官方_锤子坚果Pro2手机降回6.0.3版本教程
  12. 我们把计算机硬件系统和软件系统称为,中国大学MOOC:\我们把计算机硬件系统和软件系统总称为( )。\;...
  13. 分享给学弟学妹们的一些成为全栈工程师的方向和方法
  14. 如何在电脑上下载python中文版_Python下载-Python中文版官方下载
  15. 美团Java面试题,苹果手机java编程软件
  16. mysql rpm怎么用_linux下mysql(rpm)安装使用手册
  17. 2022-2028全球与中国定时器市场现状及未来发展趋势
  18. 利用sikuli插件辅助实现自动化脚本
  19. 西门子200Smart加维纶触摸屏程序画面程序案例,项目内容为某制造企业疫苗车间控制系统,报告配液工艺
  20. 报错:from .. import deform_conv_cuda

热门文章

  1. 常用php操作redis命令整理(五)ZSET类型
  2. 事件类型-UI事件、焦点事件
  3. bzoj 1930: [Shoi2003]pacman 吃豆豆 [费用流]
  4. PHP图形图像的典型应用 --常用图像的应用(统计图)
  5. 《一个程序员的奋斗史》帮我选封面哇! —— 猜封面页数赢赠书活动~
  6. Silverlight中动画的性能浅析
  7. 关于异常信息未找到成员
  8. jar包导出无法显示图片或者音乐_超详细微信表情包制作教程
  9. Android8.0前后Camera架构对比(二十三)
  10. 重启framework命令及framework.jar引用