《数据库索引设计优化》读书笔记(七)

本文深入探讨了数据库索引选项,并通过MySQL和Oracle实例对比,揭示了索引行压缩、唯一性约束、从两个方向扫描索引等特性的差异,以及索引键截断、基于函数的索引、索引跳跃式扫描和块索引等功能的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第13章 数据库索引选项

练习

13.1 调查你当前使用的 DBMS 版本关于索引的限制和高级选项。

  • 索引行压缩与异常情况

        MySQL 支持
        Oracle 支持

        MySQL 使用 NULL 值实现索引行压缩。但不推荐在实际中使用 NULL 来代替一个特定的值,因为从长远来看,这可能会导致应用系统错误。

create table t1 (a int);
insert into t1 values (1),(2),(3),(null),(4),(null),(5),(null);
commit;
select count(*) from t1;
create unique index idx1 on t1(a);

explain select * from t1 where a=1;
explain select * from t1 where a is null;


        表中有三个 NULL 值,但唯一索引创建成功。从图1 可以看到,查询 NULL 值的记录使用了 idx1 的索引覆盖,但 type 类型却是 ref,表示索引的数据值是非唯一的。从 Extra 列的 Using where 可以看到需要过滤元组,可见多行 NULL 值被压缩成一个唯一键值。

  • 索引键以外的其它索引列

        MySQL 不支持
        Oracle 不支持

        索引包含的列(Included Columns / Covered Columns)指的是:不参与查找,但存储在索引中,避免回表查询以减少 I/O。例如:

CREATE INDEX idx_user_orders ON orders (user_id) INCLUDE (order_date, amount);

        SQL Server、PostgreSQL 支持索引包含列。

  • 唯一性约束

        MySQL 不支持
        Oracle 支持

create table t1(a int,b varchar2(20));
create index idx1 on t1(a,b);
alter table t1 add primary key (a);
select index_name,uniqueness from user_indexes;

        查询结果如图2 所示

select constraint_name,constraint_type from user_constraints;

        查询结果如图3 所示

        从图2 可以看到,表 t1 上只有一个非唯一索引 idx1。从图3 可以看到,表 t1 上有一个主键约束。索引 idx1 可以被用来约束主键 a 的唯一性。这可以通过引入 primary key 约束来做到。

        再来看 MySQL:

create table t1(a int,b varchar(20));
create index idx1 on t1(a,b);
alter table t1 add primary key (a);
show index from t1;

        查询结果如图4 所示

        MySQL 在主键上新建了一个名为 PRIMARY 的索引,而没有使用已有的 idx1 索引加主键约束的方式。

  • 从两个方向扫描索引

        MySQL 支持
        Oracle 支持

create table t1 as select * from dba_objects;
create index idx1 on t1(owner,object_id);
exec dbms_stats.gather_table_stats(ownname=>'WXY',tabname => 'T1',estimate_percent=> 20 , cascade=> TRUE );
set autotrace traceonly;
select * from t1 where owner='SYS' and object_id > 50000 order by object_id desc;

        查询结果如图5 所示,进行了索引范围逆向扫描。


        再来看 MySQL:

create table t1 as select * from information_schema.tables;
create index idx1 on t1(table_schema,table_name);
explain select * from t1 where table_schema='test' order by table_name desc;
explain select * from t1 where table_schema='test' order by table_name;

        查询结果如图6 所示,无论是正向还是反向 order by,都是使用的索引扫描,没有额外的排序。

  • 索引键截断

        MySQL 支持
        Oracle 不支持

        索引键截断是指数据库系统在创建索引时,如果索引键(Index Key)的长度超过限制,会自动截断部分数据,仅保留前 N 个字节作为索引键,如 MySQL 的 InnoDB 限制为 3072 字节。 Oracle 的索引键长度无硬性限制,但建议不超过 1000 字节。

  • 基于函数的索引

        MySQL 不支持
        Oracle 支持

  • 索引跳跃式扫描

        MySQL 支持(Loose Index Scan)一个例子MIN on a composite index at EXPLAIN EXTENDED
        Oracle 支持(INDEX SKIP SCAN)

  • 块索引

        MySQL 不支持
        Oracle 支持(cluster index)

  • 数据分区的二级索引

        MySQL 分区表只支持本地索引。
        Oracle 分区表支持本地索引(Local)和全局索引(Global)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值