`
liangguanhui
  • 浏览: 113145 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

自斟自饮——6. 唯一性索引

阅读更多



Unique Index,唯一性索引,相信each of us都知道是怎么一回事。相对于普通的index,唯一性索引多了一个检查唯一性的checking。但,你对这个Unique Index是不是真的已经非常了解了?是吗?

1. 假设有以下表结构:

create temp table tmp_one (tid integer, tname char(12));
create temp table tmp_two (tid integer, tno integer, tname char(12));

create unique index tmp_one_idx on tmp_one(tid);
create unique index tmp_two_idx on tmp_two(tid, tno);

你觉得下面的代码执行结果是怎么样?

-- first
insert into tmp_one values (1, 'a');
insert into tmp_one values (2, 'b');
insert into tmp_one values (2, 'c');
insert into tmp_one values (null, 'd');
insert into tmp_one values (null, 'e');

-- second
insert into tmp_two values (1, 1, 'a');
insert into tmp_two values (2, 1, 'b');
insert into tmp_two values (2, 1, 'c');
insert into tmp_two values (null, 1, 'd');
insert into tmp_two values (null, 1, 'e');
insert into tmp_two values (null, null, 'f');
insert into tmp_two values (null, null, 'g');

-- finally query
select * from tmp_one order by tid;
select * from tmp_two order by tid, tno;

你觉得这个结果在Informix、MySQL、Oracle、PostgreSQL是否会一样呢?你觉得为什么会有这样的不同?


2. 有以下一个business表

create table business (
    tid     integer,
    tkind   char(1),
    tname   char(12)
);

现在有这样一个需求,对于所有tkind = ‘Y’的数据,tid都必须是唯一的,其余的tkind != ‘Y’ 或者null的数据不受这个限制。请问你会如何建这个“部分唯一性”的索引?


3. 假若存在一个表,

create table thing (
    tid       integer,
    handled   char(1),     --这个标志位表示是否已经被day-end处理过,Y或者N
    data      char(300)
);
create unique index thing_idx on thing(tid);

假若thing表有1000w数据,handled列都是“Y”,然后每天会有一些front-end插入一些handled = ‘N’的记录(数量大概几百条的样子),接着每天晚上会有一个day-end把这些handled = ‘N’的数据取出来,处理完后,最后会把这些记录的handled update成“Y”。

--伪代码
for row in (select * from thing where handled = 'N' for update)
begin
    -- 这里我省略了处理这条row的代码
    update thing set handled = 'Y' where in current row
end

你会怎样改善这个过程?


























1. NULL在索引的问题

这个NULL的问题在不同的数据库表现很不一样,informix把它看作一个普通的值;但在Oracle、MySQL、PostgreSQL中的情况完全相反——NULL不起作用。不过要留意,这里的“不起作用”还是有异同的。

简单来说,好像按照SQL标准(不知道是SQL92还是SQL99了),不应该对null进行索引,in other word,索引中不应该包含null,(注意,虽然我给出的例子是unique index,但普通索引也一样成立的,只不过unique index比较容易看到实验效果)

先列出Informix的结果:



下面是MySQL的结果:



然后是pgsql的结果:



最后是oracle的结果:



从上面的结果我们可以得到很多很多的信息。



大家可以看到,在这一方面pgsql竟然“背叛”了oralce,跟MySQL相同。

我不知道大家有没有留意,反正我是在写这篇文章的时候才留意到,这四个数据库对于NULL排序是有不同的。

在ASC升序的情况下,
Informix、MySQL是把NULL放在前面;pgsql和oracle把NULL放在最后。
相信在DESC降序时,情况会是倒过来的。

这个测试说明了:
  • 不同的数据有不少关键地方是不同的,平时要多加笔;
  • 对于unique index,如果业务允许,尽量增加not null的约束。

虽然几个数据库对NULL在索引上的表现有所不同,但Informix似乎是“独占鳌头”了,尽管我不怎么想说Informix烂


2.NULL在索引中的妙用

对于“部分唯一性”的约束,可能有人建议trigger。但实际情况下会有很多很多很多的问题。

首先是性能的问题,trigger绝对是性能杀手的重要一员,一个不留神就会中招。

其次是隔离级别的问题,不同隔离级别下看到的数据是不一样的,例如对于informix,如果别人的数据还没有commit,我们在read uncommitted下是可以得到的,但在其余的隔离级别是看不到的。这种“多样性”会导致很多判断上的分歧,令我们的系统存在不少“隐患”。

最后,我有点怀疑是否真的能够实现。因为数据库存在并发,我们当然需要对数据加锁,但一般数据库都没有类似MySQL(InnoDB)的“间隙锁”,似乎很难对不存在的数据进行加锁,即使是MySQL(InnoDB),间隙锁也必须是在repeatable read和serializable才有效,有一定的局限性。

实际上我们可以利用NULL不索引这个特性建立“部分唯一性”索引(或者叫有选择性的索引、有条件的索引)。

首先我们建一个function(这里以oracle为例)。可能很多人都不知道现在的数据库都可以create function的,实际上function跟procedure存储过程很相似,只是function必须有返回值。这个函数很简单,对于tkind = Y,返回实际的id,否则统统返回null。

create function test_fn1 (f_id in integer, f_kind in char(1)) return integer
deterministic
as
begin
    if f_kind = 'Y' then
        return f_id
    end if
    return null
end;
/

然后对表business建一个function index(函数索引)。要了解更多关于函数索引可以google一下。

create unique index busi_idx1 on business (test_fn1(tid, tkind));

这个时候已经可以实现部分唯一性约束了。因为这个函数只会对tkind = ‘Y’的数据返回真正的tid,其余的tkind都是返回null,所以我们的索引也就只对tkind = Y起作用了。我们知道null是不进入索引的。

注意:由于informix对null也会收录到index,所以这个方法对于Informix无效。如果你问我infomix下怎么搞,我answer:不知道。


3. 附加练习题

这一道附加题我就不打算细说了,看完上面估计大家都应该知道怎么做。
  • 大小: 4.8 KB
  • 大小: 3.1 KB
  • 大小: 4 KB
  • 大小: 4.1 KB
  • 大小: 3.3 KB
  • 大小: 59.4 KB
3
3
分享到:
评论

相关推荐

    数据库 索引————1.ppt

    数据库原理————1.ppt,西南交大……资料

    数据分析核心知识点总结 —— SQL.pdf

    - 唯一索引:确保索引键的唯一性。 - 非唯一索引:允许重复的索引键。 - 组合索引:基于多个列创建索引。 - 反向键索引(Oracle):适用于字符串排序。 - 函数索引:基于函数结果创建索引。 - 索引组织表...

    mysql主键和唯一索引的区别(csdn)————程序.pdf

    相对地,唯一索引是一种索引类型,它的主要目的是加速查询并确保特定列的值具有唯一性,但并不强制该列的值不能为空。因此,唯一索引允许出现NULL值,这是它与主键的一个显著区别。你可以为一张表创建多个唯一索引,...

    最新数据库——2009.09.23

    6. 数据库性能优化:通过索引、查询优化、分区、存储优化等手段提高数据库的响应速度。 7. 数据库安全:涉及用户权限管理、访问控制、审计和加密,确保数据的安全性和隐私保护。 8. 数据备份与恢复:定期备份...

    参考资料-土方分部(第6卷)——目录.zip

    【描述】的简洁性表明,这个压缩包主要包含了一个名为"土方分部(第6卷)——目录.doc"的文档,这是一个Microsoft Word格式的文件。通常,目录是任何大型文档或项目的关键组成部分,它列出了所有章节、子章节以及...

    学习笔记——sql.zip

    索引(INDEX)是提升数据库查询速度的关键,有唯一索引、主键索引、非唯一索引等多种类型。事务(TRANSACTION)用于确保数据库操作的原子性、一致性、隔离性和持久性,是数据库系统中的重要概念。最后,SQL还有...

    71.紫光科技园规划——GBBN.zip

    紫光科技园规划——GBBN.zip 是一个数据集压缩包...通过对紫光科技园规划——GBBN.zip中提供的数据进行深入挖掘和分析,专业人士可以为紫光科技园区提供一套科学、全面且具有前瞻性的规划方案,以推动园区的健康发展。

    Mysql 的InnoDB引擎相关读书笔记

    1.3.2.InnoDB磁盘结构——索引.md 1.3.3.InnoDB磁盘结构——表空间.md 1.4.0.Mysql文件——参数文件.md 1.4.1.0.Mysql文件——日志文件.md 1.4.2.Mysql文件——socket文件.md 1.4.3.Mysql文件——pid文件.md 1.4.4.0...

    python、numpy、Pytorch中的索引方式(csdn)————程序.pdf

    在Python、NumPy和PyTorch中,索引和切片是访问和操作数组或张量数据的关键方式。本文将详细解析这三种语言环境下的不同索引类型。 首先,我们来看Numpy中的索引方式: 1. **下标索引**:在Numpy中,下标索引允许...

    每日一练python20(csdn)————程序.pdf

    6. **类型提示(Type Hints)**:在Python 3.5及更高版本中,可以使用类型提示来增强代码的可读性和可维护性。例如,在函数定义中,`nums: List[int]`表示`nums`参数应该是一个整数列表。 7. **力扣(LeetCode)**:...

    python笔记03(csdn)————程序.pdf

    在这个"python笔记03(csdn)——程序"中,主要探讨的是关于Python列表操作的一些基本知识点,这些知识点对于理解和操作Python列表至关重要。 1. **更改列表**: 列表的更改分为单个元素的更改和范围更改。单个...

    参考资料-施工记录(第4卷)——目录.zip

    在IT行业中,管理和组织大量的项目文档是至关重要的。在给定的压缩包文件"参考资料-施工记录(第4卷)——目录....在IT领域,类似的文档管理方式同样适用于软件开发、系统集成等项目,确保团队工作的有序性和可追溯性。

    简单租房项目学习——mysql.zip

    在“简单租房项目学习——mysql.zip”这个压缩包中,我们可以推测这是一份关于使用MySQL数据库来构建一个租房项目的教学资源。在这个项目中,我们可能会涉及到数据库设计、SQL语句编写、数据操作以及如何将这些...

    牛逼!MySQL 8.0 中的索引可以隐藏了…(csdn)————程序.pdf

    在MySQL 8.0中,隐藏索引是一个重要的新特性,它允许数据库管理员在不影响查询优化的情况下测试索引对查询性能的影响。隐藏索引并非真正地“消失”,而是使其在查询优化过程中不可见,从而避免在性能分析时进行耗时...

    mysql进阶学习一之知识点总结(csdn)————程序.pdf

    6. **索引失效情况**: - 索引可能因不合规的SQL写法而失效,如未遵循最左前缀原则、使用`!=`或`IS NOT NULL`判断、`LIKE`模糊查询时百分号在前、对索引列使用函数或不正确地处理字符串类型字段。 7. **关联查询...

    Python——pandas模块—Series数据结构(csdn)————程序.pdf

    值得注意的是,虽然字典中的键是唯一的,但Series的索引可以重复: ```python dic = {'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000} a = pd.Series(dic) ``` 访问Series有多种方法。`Series.head()`用于...

    参考资料-附属构筑物分部(第9卷)——目录.zip

    【压缩包子文件的文件名称列表】中唯一的一个文件名“附属构筑物分部(第9卷)——目录.doc”表明这个文档是Microsoft Word格式,通常用于撰写报告或详细的技术文档。这个文档很可能是该卷资料的详细目录,列出了...

    python 列表(csdn)————程序.pdf

    6. 插入元素 `insert()`方法用于在指定位置插入一个元素,如`names.insert(1, "Liumm")`在索引1处插入"Liumm"。 7. 修改元素 直接通过索引访问并赋值即可修改列表中的元素,如`names[2] = "Maso"`。 8. 删除元素...

    第三章 python基础(csdn)————程序.pdf

    例如:"hello"可以被索引为h、e、l、l、o,索引从0开始,到达字符串的长度减一为止。 基本操作包括: 1. 索引:返回字符串中单个字符。<字符串>[M],其中M是索引值。 2. 切片:返回字符串中一段字符子串。<字符串>...

    python学习导航(csdn)————程序.pdf

    本"Python学习导航(CSDN)——程序"教程将指导你深入理解Python编程,无论你是从其他编程语言转行,如JavaScript、Java或C++,还是初次接触编程,都能从中受益。 首先,让我们从基础开始。Python的基础包括: 1. ...

Global site tag (gtag.js) - Google Analytics