zoukankan      html  css  js  c++  java
  • 数据库联合索引+空值的索引使用问题

    昨天在QQ群里讨论一个SQL优化的问题,语句大致如下:

    select A,min(B) from table group by A;
    --A,B都没有not null约束,A列无空值,B列有空值。
    --存在复合索引IX_TEST(A,B)

    于是手动测试,先看Oracle,环境采用Oracle自带的scott用户下的emp表。

    1.首先查看如下语句的执行计划(此时表只有主键索引):

    2.添加IX_TEST(deptno,comm)后查看执行计划:

    发现依然是全表扫描。

    3.为deptno列添加非空约束后再次查看执行计划:

    SQL Server的相关测试流程基本一致。

    Tom在《Expert one on Oracle》中说:Oracle数据库中,除位图索引和聚簇索引外,单列Btree索引节点是不存储空值的。联合索引只要有一个列不为空,Btree节点就会存储索引键值。

    在本例中我们创建了(deptno,comm)的联合索引,如果deptno没有非空约束优化器选择全表扫描,如果有非空约束优化器选择索引全扫描。说明添加非空约束后Oracle认为所有的记录都已经被包含在了索引中因此无需全表扫描。

    因此在Oracle中一定要为联合索引的首列设置非空约束。

    4.MySQL测试

    在MySQL中这个问题稍微复杂一点,因为MySQL的NULL值和空字符是有区别的,本文只测试innodb存储引擎(MySQL5.7.22版本)。

    首先把SCOTT的数据从oracle完全搞到MySQL,除了EMP表外其他3个表的使用navicat即可同步,EMP表由于HIREDATE的日期类型,需要先自己在MySQL端创建表然后使用PLSQL Developer导出SQL插入语句然后将其在MySQL端执行,如下是当前的EMP表数据:

    创建索引后结果如下:

    可见在Mysql Innodb中无论复合索引首列是否存在非空约束,都会使用索引,这点与Oracle不同。

    那么innodb中如果索引中存在NULL值,还会使用索引吗?继续测试:

     

    可以看到存在NULL值,innodb也会走索引,那么空字符呢?

    继续测试发现无论字符类型的列中存储的是NULL还是空字符''都是会走索引的。

    在3大关系型数据库中,B+tree索引结构最为明了的反而是SQL Server,从dump出来的索引页我们可以看到SQL Server的Btree索引是存储null值的,即便全部都是空也会存储空值+主键书签。而且以上涉及的SQL全部会使用到联合索引,这点不但方便使用而且也很容易想通。

    更多更详细的测试有待继续补充。

    最后:Oracle数据库列能添加非空约束的一定要添加,MySQL、SQLServer中可能没这么严格。

  • 相关阅读:
    Python常用模块之sys
    python操作zip文件
    python的os模块
    [Python模块学习]用qrcode模块生成二维码
    os模块os.walk() 方法和os.path.join()的简单使用
    python操作redis详解
    成员变量和局部变量
    类和对象 引用属性和方法举例
    Java String字符串/==和equals区别,str。toCharAt(),getBytes,indexOf过滤存在字符,trim()/String与StringBuffer多线程安全/StringBuilder单线程—— 14.0
    泛型--面向对象8
  • 原文地址:https://www.cnblogs.com/leohahah/p/8425813.html
Copyright © 2011-2022 走看看