--随机数
select trunc( dbms_random.value(1,3) ) from dual;
--这个随机添加太有意思了
select decode(trunc( dbms_random.value(1,3) ),1,'M',2,'F') from dual;
--收获,不止oracle 讲解索引的总页数: 136
select 326 -190 from dual ;
索引在应用主要有三类:
B-TREE索引
位图索引
函数索引
分区表的本地索引
索引结构分为:根 分支 叶
一般通过索引访问数据 至少经过3次IO以上
索引有三个特点
1.索引树的高度一般都比较低 500G的索引树高度也就6层
2.索引由列值和rowid组成
3.索引是有序的
select * from RANGE_PART_TAB partition (PAR_LIST_09)
-- 查看段数据
select t.segment_name,
t.partition_name,
t.segment_type,
t.tablespace_name,
t.BYTES / 1024
from user_segments t
where t.segment_type = upper('TABLE PARTITION');
-- 查看 索引高度的SQL语句
select t.INDEX_NAME,
t.blevel,
t.LEAF_BLOCKS,
t.NUM_ROWS,
t.DISTINCT_KEYS,
t.CLUSTERING_FACTOR
from user_ind_statistics t ;
--100万数据
select count(1) from t;
--创建索引所需时间: 156s
create index t_x on t(x);
drop index t_x ;
--索引高度的应用
create table t50w
as select rownum id, rownum+1 as col_name from dual connect by level <=500000;
create table t500w
as select rownum id, rownum+1 as col_name from dual connect by level <=5000000 ;
create index ind_t50w on t50w(id);
create index ind_t500w on t500w(id);
select t.INDEX_NAME,
t.blevel,
t.LEAF_BLOCKS,
t.NUM_ROWS,
t.DISTINCT_KEYS,
t.CLUSTERING_FACTOR
from user_ind_statistics t
where lower(t.TABLE_NAME) in('t50w','t500w')
/*
1 IND_T50W 2 1113 500000 500000 1035
2 IND_T500W 2 11705 5000000 5000000 11462
*/
--71 consistent gets 4 (0)| 00:00:01 |
select * from t50w t where t.id = 123465 ;
--73 consistent gets 4 (0)| 00:00:01
select * from t500w t where t.id =1237654 ;
--结论 因为高度一样 所以50万数据和500万数据通过索引扫描 获取的数据的时间是一样的
--经过测试 索引只适合返回10%总记录的数据
select (49970 / count(1)) *100 || '%' from t50w ;
select (610000/count(1)) *100 || '%' from t500w ;
--183 consistent gets 132 (2)| 00:00:02
select count(*) from t50w t where t.id <= 49970;
--1433 consistent gets 1280 (2)| 00:00:16
select count(*) from t500w t where t.id <=610000 ;
/*在cmd 中 sqlplus使用以下语句查看sql的执行计划 */
sqlplus scott/tiger
set autotrace on;
set linesize 1000;
set timing on;
--set autotrace traceonly;
/*==============分区索引的应用==================*/
--如果设置了分区索引却用不到分区条件,性能将下降
select count(1) from RANGE_PART_TAB t ;
--在RANGE_PART_TAB 上创建'分区索引 ' ,也就是要加上local
create index ind_range_tb_id on RANGE_PART_TAB(id) local;
select count(1) from norm_TAB t ;
create index ind_norm_tb_id on norm_TAB(id) ;
--性能测试
select count(*) from RANGE_PART_TAB t where t.id = 5632;
select count(*) from NORM_TAB t where t.id = 5632;
select count(*) from RANGE_PART_TAB t
where t.id = 5632 and t.deal_date = to_date('20150603','YYYYMMDD');
--
select t.segment_name,
t.partition_name,
t.segment_type,
t.tablespace_name,
t.BYTES / 1024
from user_segments t
where t.segment_name in ( upper('ind_range_tb_id'), upper('ind_norm_tb_id') ) ;
sum(sal) avg(sal) count(*) 扫描数据要走索引时, 必须指定所汇总的列值为非空值.
而max() min() 走索引时,只扫最边上的索引叶 可以不指定所汇总的列值为非空值.
create index ind_t_x on t(x) ;
select min(t.x) from t;
select max , min from (select max(x) max from t ) a,(select min(x) min from t ) b ;
/**=
==消除回表==
消除 table access by index rowid 这个回表动作
可改进性能的案例占比20%左右
=*/
比如一个应用展示的字段不多,可以通过组合索引进行回表的消除,
注意:联合索引不宜列过多超过三个字段组成的联合索引都是不合适的,
因为消减了回表动作,而导致索引块变多就可能遍历更多的BLOCK了,反而影响了性能
create index idx_un_tb_id_name on tb(id,name);
--聚合因子: 索引和表之间数据顺序的相似度越高,聚合因子的值就越低
drop table t_order_1 purge;
create table t_order_1
(x number,
col_x number
);
begin
for i in 1 .. 1000000
loop
insert into t_order_1 values(i, dbms_random.value(0,10000));
end loop;
commit;
end;
/
--添加主键
alter table t_order_1 add constraint pk_t_order_1 primary key(x);
drop table t_order_2 purge ;
create table t_order_2 as
select * from t_order_1 t order by t.col_x ;
--添加主键
alter table t_order_2 add constraint pk_t_order_2 primary key(x);
select count(1) from t_order_1 ;
select count(1) from t_order_2 ;
select * from t_order_1 t where t.x > 2 order by t. x ;
select /*+index(t)*/ * from t_order_1 t where t.x > 2 order by t. x ;
/* 消除回表 table access by index rowid */
select t.x from t_order_1 t where t.x > 2 order by t. x ;
select t.INDEX_NAME,
t.blevel,
t.LEAF_BLOCKS,
t.NUM_ROWS,
t.DISTINCT_KEYS,
t.CLUSTERING_FACTOR
from user_ind_statistics t
where t.INDEX_NAME in ( upper('pk_t_order_1'), upper('pk_t_order_2') ) ;
/**
1 PK_T_ORDER_1 2 2087 1000000 1000000 4273
2 PK_T_ORDER_2 2 2087 1000000 1000000 999794
*/
--order by 排序优化
--DISTINCT 排重优化
--union 合并优化
--主外键的作用 级联删除
--位图索引
select sysdate,trunc(sysdate) from dual ;
drop table t_date_tst purge;
create table t_date_tst(col_date date) ;
begin
for x in 1 .. 120000
loop
insert into t_date_tst
select sysdate - dbms_random.value(0,13) from dual;
end loop;
commit;
end;
select * from t_date_tst;
CREATE INDEX IND_t_date_tst_col_date on t_date_tst(col_date) ;
select count(*) from t_date_tst t where trunc(t.col_date) >= to_date('20160402','YYYYMMDD') AND trunc(t.col_date) <= to_date('20160403','YYYYMMDD');
select count(*) from t_date_tst t where t.col_date >= to_date('20160402','YYYYMMDD') AND t.col_date < to_date('20160403','YYYYMMDD')+ 1