唯一索引与非唯一索引区别(UNIQUE INDEX, NON-UNIQUE INDEX)
索引是我们经常使用的一种数据库搜索优化手段。适当的业务操作场景使用适当的索引方案可以显著的提升系统整体性能和用户体验。在Oracle中,索引有包括很多类型。不同类型的索引适应不同的系统环境和访问场景。其中,唯一性索引Unique Index是我们经常使用到的一种。
唯一性索引unique index和一般索引normal index最大的差异就是在索引列上增加了一层唯一约束。添加唯一性索引的数据列可以为空,但是只要存在数据值,就必须是唯一的。
那么,在使用唯一性索引时,同一般索引有什么差异呢?下面通过一系列的演示实验来说明。
1、实验环境准备
为了体现出一致性和可能的差异性,选择相同的数据值列加入不同类型的索引结构。
SQL> select * from v$version where rownum<2;
BANNER
--------------------------------------------------------------------------------
Oracle Database11gEnterpriseEdition Release11.2.0.1.0 - Production
SQL> create table t as select * from dba_objects;
Table created
//保证data_object_id和object_id取值相同;
SQL> update t set data_object_id=object_id;
72581 rows updated
SQL> commit;
Commit complete
//普通索引
SQL> create index idx_t_normalid on t(object_id);
Index created
//唯一性索引
SQL> create unique index idx_t_uniid on t(data_object_id);
Index created
SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true);
PL/SQL procedure successfully completed
2、体积容量比较
在环境准备中,我们将索引列取值设置为完全相同,尽量避免由于外在原因引起的差异。下面我们检查数据字典中的容量比较信息。
首先是查看索引段index segment信息。
SQL> select segment_name, segment_type, bytes, blocks, extents from dba_segments where segment_name in ('IDX_T_NORMALID','IDX_T_UNIID');
SEGMENT_NAME SEGMENT_TYPE BYTES BLOCKS EXTENTS
-------------------- ------------------ ---------- ---------- ----------
IDX_T_NORMALID INDEX 983040 120 15
IDX_T_UNIID INDEX 917504 112 14
一般索引normal index较唯一性索引空间消耗略大。索引idx_t_normalid占据15个分区,120个block。略大于idx_t_uniid的14个分区块。
这个地方需要注意一下,在数据字典中一个segment的分区占据,是Oracle系统分配给的空间,并不意味着全部使用殆尽。可能两个索引结构差异很小,但是额外多分配出一个extent。
索引叶子结构上,检查数据字典内容。
SQL> select index_name, index_type, UNIQUENESS, BLEVEL, LEAF_BLOCKS, DISTINCT_KEYS from dba_indexes where index_name in ('IDX_T_NORMALID','IDX_T_UNIID');
INDEX_NAME INDEX_TYPE UNIQUENESS BLEVEL LEAF_BLOCKS DISTINCT_KEYS
-------------------- --------------- ---------- ---------- ----------- -------------
IDX_T_UNIID NORMAL UNIQUE 1 106 51330
IDX_T_NORMALID NORMAL NONUNIQUE 1 113 51330
两者的差异不大,normal index空间消耗要略大于unique index。
结论:从数据字典反映出的情况可以知道,同一般索引相比,唯一性索引的空间消耗略小一些。由于我们采用的实验数据都是相同的,这一点点的差距可能就意味着两种索引类型在存储结构上存在略微的差异。
3、违反约束实验
作为唯一性索引,在添加创建和进行dml操作的时候,都会严格发挥出约束的作用。
SQL> insert into t select * from t where rownum<2;
insert into t select * from t where rownum<2
ORA-00001:违反唯一约束条件(SYS.IDX_T_UNIID)
4、等号检索实验
当我们进行等号查询的时候,Oracle对两种索引生成的执行计划有何种差异?注意:下面的select检索之前,都使用flush语句对shared_pool和buffer_cache进行清理。
--精确查询
SQL> select * from t where object_id=1000;
执行计划
----------------------------------------------------------
Plan hash value: 776407697
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 101 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 101 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_T_NORMALID | 1 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=1000)
统计信息
----------------------------------------------------------
528 recursive calls
0 db block gets
87 consistent gets
11 physical reads
0 redo size
1200 bytes sent via SQL*Net to client
376 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
4 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * from t where data_object_id=1000;
执行计划
----------------------------------------------------------
Plan hash value: 335537167
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 101 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 101 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | IDX_T_UNIID | 1 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DATA_OBJECT_ID"=1000)
统计信息
----------------------------------------------------------
528 recursive calls
0 db block gets
86 consistent gets
10 physical reads
0 redo size
1200 bytes sent via SQL*Net to client
376 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
4 sorts (memory)
0 sorts (disk)
1 rows processed
这里,我们看到了Unique Index的一个特性,就是等号操作时执行计划的差异。对Unique Index而言,进行相等查询的结果只有一行值或者没有,所以没必要进行传统的Index Range Scan操作。此处,执行计划中使用的是Index Unique Scan操作,直接精确定位到指定的记录项目,返回rowid记录。
而一般索引在进行等号检索的时候,通常使用的就是Index Range Scan操作。沿着索引树叶子节点进行水平扫描操作,直到获取索引符合条件索引列值的rowid列表。
从成本上看,两者虽然执行计划操作方式有一定差别,但是成本实际差异不大。CPU成本和执行时间上相同。各种块读操作(逻辑读和物理读)存在一些差异,笔者认为源于两个索引结构的微量区别,这样读取的块数一定有些差异。
5、范围搜索实验
当我们进行索引列的范围搜索时,执行计划和成本有何种差异呢?
--范围匹配
SQL> select * from t where object_id>=1000 and object_id<=1500;
已选择490行。
执行计划
----------------------------------------------------------
Plan hash value: 776407697
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 485 | 48985 | 14 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 485 | 48985 | 14 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_T_NORMALID| 485 | | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID">=1000 AND "OBJECT_ID"<=1500)
统计信息
----------------------------------------------------------
528 recursive calls
0 db block gets
158 consistent gets
17 physical reads
0 redo size
23775 bytes sent via SQL*Net to client
728 bytes received via SQL*Net from client
34 SQL*Net roundtrips to/from client
4 sorts (memory)
0 sorts (disk)
490 rows processed
SQL> select * from t where data_object_id>=1000 and data_object_id<=1500;
已选择490行。
执行计划
----------------------------------------------------------
Plan hash value: 2700411221
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 485 | 48985 | 14 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 485 | 48985 | 14 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_T_UNIID | 485 | | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DATA_OBJECT_ID">=1000 AND "DATA_OBJECT_ID"<=1500)
统计信息
----------------------------------------------------------
528 recursive calls
0 db block gets
157 consistent gets
16 physical reads
0 redo size
23775 bytes sent via SQL*Net to client
728 bytes received via SQL*Net from client
34 SQL*Net roundtrips to/from client
4 sorts (memory)
0 sorts (disk)
490 rows processed
从实验结果看,两者在进行范围搜索时,执行计划没有差异。两者都是进行Index Range Scan操作。各类型成本基本相同。
6、结论
本篇主要从应用角度,分析Unique Index与一般normal Index的差异。从结果看,Unique Index就是额外添加的唯一性约束。该约束严格的保证索引列的取值唯一性,这在一些数据列上的业务约束实现是很重要的功能。比如一个数据列,不能作为主键,而且允许为空,但是业务上要求唯一特性。这时候使用唯一性索引就是最好的选择。
从执行计划where条件中的表现看,Unique Index和一般normal Index没有显著性的差异。
两者数据基础值一样的情况下,生成索引的体积存在略微的差异,说明在存储结构上两者可能有不同。下面我们来分析一下两类型索引的结构信息。
原文地址:https://www.cnblogs.com/sarahc/articles/2112891.html
唯一索引与非唯一索引区别(UNIQUE INDEX, NON-UNIQUE INDEX)的更多相关文章
- SQL Server索引 - 聚集索引、非聚集索引、非聚集唯一索引 <第八篇>
聚集索引.非聚集索引.非聚集唯一索引 我们都知道建立适当的索引能够提高查询速度,优化查询.先说明一下,无论是聚集索引还是非聚集索引都是B树结构. 聚集索引默认与主键相匹配,在设置主键时,SQL Ser ...
- SQL有三个类型的索引,唯一索引 不能有重复,但聚集索引,非聚集索引可以有重复
重要: (1) SQL如果创建时候,不指定类型那么默认是非聚集索引 (2) 聚集索引和非聚集索引都可以有重复记录,唯一索引不能有重复记录. (3) 主键 默认是加了唯一约束的聚集索引,但是也可以在主键 ...
- SQL存储原理及聚集索引、非聚集索引、唯一索引、主键约束的关系(补)
索引类型 1. 唯一索引:唯一索引不允许两行具有相同的索引值 2. 主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型.主键索引要求主键中的 ...
- SQL聚集索引和非聚集索引的区别
其实对于非专业的数据库操作人员来讲,例如软件开发人员,在很大程度上都搞不清楚数据库索引的一些基本知识,有些是知其一不知其二,或者是知其然不知其所以然.造成这种情况的主要原因我觉的是行业原因,有很多公司 ...
- 你能说出SQL聚集索引和非聚集索引的区别吗?
最近突然想起前一阵和一朋友的聊天,当时他问我的问题是一个非常普通的问题:说说SQL聚集索引和非聚集索引的区别. AD:WOT2015 互联网运维与开发者大会 热销抢票 其实对于非专业的数据库操作人员来 ...
- mysql 聚集索引,非聚集索引,覆盖索引区别。
把原站信息经过筛选贴过来,用于自己备忘.原站:https://www.cnblogs.com/aspwebchh/p/6652855.html ---------------------------- ...
- SQL Server - 索引详细教程 (聚集索引,非聚集索引)
转载自:https://www.cnblogs.com/hyd1213126/p/5828937.html 作者:爱不绝迹 (一)必读:深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录. ...
- SQLSERVER聚集索引与非聚集索引的再次研究(下)
SQLSERVER聚集索引与非聚集索引的再次研究(下) 上篇主要说了聚集索引和简单介绍了一下非聚集索引,相信大家一定对聚集索引和非聚集索引开始有一点了解了. 这篇文章只是作为参考,里面的观点不一定正确 ...
- SQL Server索引 (原理、存储)聚集索引、非聚集索引、堆 <第一篇>
一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都 ...
- 聚集索引VS非聚集索引
聚集索引VS非聚集索引 SQL Server 2014 发布日期: 2016年12月 索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度. 索引包含由表或视图中的一列或多列生成的键. ...
随机推荐
- windows 环境下搭建docker私有仓库
windows 环境下搭建docker私有仓库 1.在公用仓库中pull仓库镜像 docker pull regitry 2.启动仓库镜像 //-d意思是后台运行,-p是做端口映射,这里是将本地的50 ...
- Oracle存储函数,存储过程
一.Oracle存储函数:存储的PL/SQL语法块,完成特定的功能.1.语法: 函数关键字: function (1)创建函数 CREATE [OR REPLACE] FUNCTION <fun ...
- 跟我一起做一个vue的小项目(一)
项目架子 npm install --global vue-cli vue init webpack travel cd travel/ npm run dev 运行效果 添加home页及其路由,添加 ...
- stack的基本使用方式
#include <iostream> #include <stack>//头文件 using namespace std; stack<int> S; int m ...
- cf round 480E The Number Games
题意:给一棵树,点$i$的点权是$2^i$,你需要删掉$k$个点,使得剩下的点连通的情况下剩下的点权值和最大. $k \leq n \leq 10^6$ 如果考虑删哪些点,是不好考虑的,会出问题. 反 ...
- C#和JS交互 WebBrowser实例
本文实现了WebBrowser的简单例子 1.引用System.Windows.Froms.dll 2.引用WindowsFormsIntegration.dll 代码如下: public parti ...
- 【JZOJ3295】【SDOI2013】泉(spring)
╰( ̄▽ ̄)╭ 济南市"泉历史研究小组"依据济南特有的泉脉关系将济南的泉水分为六个区域,分别是市中区.历下区.天桥区.槐荫区.历城区.长清区. 作为光荣的济南泉历史研究小组中的一员 ...
- 关于chrome浏览器的帐号密码自动填充以及出现的黄色背景色填充问题
不知道大家平时做项目的时候有木有关注这个问题,其实之前做项目遇到过类似的问题,但是因为是单独的chrome浏览器的填充,而且是样式问题稍微严重点,也就没在意.然而在近期的项目中有遇到了这个问题,最为一 ...
- NOIP模拟 7.05
Problem 1 双色球(ball.cpp/c/pas) [题目描述] 机房来了新一届的学弟学妹,邪恶的chenzeyu97发现一位学弟与他同名,于是他当起了善良的学长233 “来来来,学弟,我考你 ...
- npm run dev 和 npm run serve
1.ERR引发的思考 创建好的 vue 项目直接执行 vue run dev 报错?运行 vue run serve 就可以启动...如下 npm run dev npm ERR! missing s ...