具有或不具有唯一列的唯一索引性能
Unique index performance with or without unique column
当唯一索引列对相关列也有唯一约束时,性能是否有任何差异?
我知道唯一索引和非唯一索引在性能上存在差异。
但我的问题是,如果列同时具有唯一约束和唯一索引,以及只有唯一索引而没有唯一约束,性能上是否会有差异?
另一个问题是,列统计信息对唯一索引的使用有影响吗?
Oracle 数据库策略具有(唯一)索引的唯一约束。
检查重复条目、查询table等时,数据库将使用索引。不是约束。所以在大多数情况下,性能会相同:
create table t (
c1 int, c2 int
);
alter table t
add constraint u
unique ( c1 );
create unique index ui
on t ( c2 );
insert into t
with rws as (
select level x from dual
connect by level <= 10000
)
select x, x from rws;
commit;
exec dbms_stats.gather_table_stats ( user, 't' ) ;
alter session set statistics_level = all;
set serveroutput off
select * from t
where c1 = 1;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 1 |00:00:00.01 | 3 |
|* 2 | INDEX UNIQUE SCAN | U | 1 | 1 | 1 |00:00:00.01 | 2 |
----------------------------------------------------------------------------------------------
select * from t
where c2 = 1;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 1 |00:00:00.01 | 3 |
|* 2 | INDEX UNIQUE SCAN | UI | 1 | 1 | 1 |00:00:00.01 | 2 |
----------------------------------------------------------------------------------------------
有一个例外。唯一约束可以是外键的目标。而唯一索引(单独)不能:
alter table t
add constraint fk
foreign key ( c1 )
references t ( c2 );
ORA-02270: no matching unique or primary key for this column-list
alter table t
add constraint fk
foreign key ( c2 )
references t ( c1 );
假设您创建了唯一和外键约束,这使优化器能够消除某些查询中的 table。这可以带来巨大的性能优势:
select t1.* from t t1
join t t2
on t1.c1 = t2.c2;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5000 |00:00:00.01 | 202 |
| 1 | NESTED LOOPS | | 1 | 10000 | 5000 |00:00:00.01 | 202 |
| 2 | TABLE ACCESS FULL| T | 1 | 10000 | 5000 |00:00:00.01 | 60 |
|* 3 | INDEX UNIQUE SCAN| UI | 5000 | 1 | 5000 |00:00:00.01 | 142 |
-------------------------------------------------------------------------------------
select t1.* from t t1
join t t2
on t1.c2 = t2.c1;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5000 |00:00:00.01 | 60 |
|* 1 | TABLE ACCESS FULL| T | 1 | 10000 | 5000 |00:00:00.01 | 60 |
------------------------------------------------------------------------------------
Table stats 会影响优化器是否使用索引。如果您搜索小于 100 的唯一值:
select * from t
where c1 <= 100;
如果 table 中只有 100 行,优化器更有可能进行完整的 table 扫描。但如果有数百万,索引就会变得更有吸引力。
当唯一索引列对相关列也有唯一约束时,性能是否有任何差异?
我知道唯一索引和非唯一索引在性能上存在差异。
但我的问题是,如果列同时具有唯一约束和唯一索引,以及只有唯一索引而没有唯一约束,性能上是否会有差异?
另一个问题是,列统计信息对唯一索引的使用有影响吗?
Oracle 数据库策略具有(唯一)索引的唯一约束。
检查重复条目、查询table等时,数据库将使用索引。不是约束。所以在大多数情况下,性能会相同:
create table t (
c1 int, c2 int
);
alter table t
add constraint u
unique ( c1 );
create unique index ui
on t ( c2 );
insert into t
with rws as (
select level x from dual
connect by level <= 10000
)
select x, x from rws;
commit;
exec dbms_stats.gather_table_stats ( user, 't' ) ;
alter session set statistics_level = all;
set serveroutput off
select * from t
where c1 = 1;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 1 |00:00:00.01 | 3 |
|* 2 | INDEX UNIQUE SCAN | U | 1 | 1 | 1 |00:00:00.01 | 2 |
----------------------------------------------------------------------------------------------
select * from t
where c2 = 1;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 1 |00:00:00.01 | 3 |
|* 2 | INDEX UNIQUE SCAN | UI | 1 | 1 | 1 |00:00:00.01 | 2 |
----------------------------------------------------------------------------------------------
有一个例外。唯一约束可以是外键的目标。而唯一索引(单独)不能:
alter table t
add constraint fk
foreign key ( c1 )
references t ( c2 );
ORA-02270: no matching unique or primary key for this column-list
alter table t
add constraint fk
foreign key ( c2 )
references t ( c1 );
假设您创建了唯一和外键约束,这使优化器能够消除某些查询中的 table。这可以带来巨大的性能优势:
select t1.* from t t1
join t t2
on t1.c1 = t2.c2;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5000 |00:00:00.01 | 202 |
| 1 | NESTED LOOPS | | 1 | 10000 | 5000 |00:00:00.01 | 202 |
| 2 | TABLE ACCESS FULL| T | 1 | 10000 | 5000 |00:00:00.01 | 60 |
|* 3 | INDEX UNIQUE SCAN| UI | 5000 | 1 | 5000 |00:00:00.01 | 142 |
-------------------------------------------------------------------------------------
select t1.* from t t1
join t t2
on t1.c2 = t2.c1;
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5000 |00:00:00.01 | 60 |
|* 1 | TABLE ACCESS FULL| T | 1 | 10000 | 5000 |00:00:00.01 | 60 |
------------------------------------------------------------------------------------
Table stats 会影响优化器是否使用索引。如果您搜索小于 100 的唯一值:
select * from t
where c1 <= 100;
如果 table 中只有 100 行,优化器更有可能进行完整的 table 扫描。但如果有数百万,索引就会变得更有吸引力。