SQLServer索引的四个高级特性

一、Index Building Filter(索引创建时过滤)

有一些索引非常低效的,比如经常查询状态为进行中的订单,订单有99%的状态是完成,1%是进行中 ,因此我们在订单状态字段上建了一个索引,性能是提高了,但是感觉索引中保存了99%的完成状态数据是永远不会查询到的,很浪费空间。如果我们的索引在建立的时间就不保存完成状态的数据,那不是更好。 Index Building Filter就是用来解决这个问题。

SQLServer
支持,语法示例:

  1. create index idx_3 on order(status) where status=’running’
  1. create index idx_3 on order(status) where status=’running

MySQL:不支持

Oracle:不支持,可以考虑用分区解决

二、Index Include Column(索引包含列)

我们经常需要建一些组合索引,一般有两种原因:
1.通过组合索引可以提高索引过滤度
    比如订单表有会员ID和订单日期2个字段,如果我们经常要按会员和订单时间查询,

  1. Select * from order where member_id=? and order_date between ? and ?
  1. Select * from order where member_id=? and order_date between ? and ?

那建立会员ID+订单日期的索引很合适。

  1. create index idx_1 on order(member_id,order_date);
  1. create index idx_1 on order(member_id,order_date);

2.索引覆盖读取
    比如我们需要读取一个会员订单的订单ID+状态列表,SQL如下:

  1. select order_id,status from order where member_id=?
  1. select order_id,status from order where member_id=?

如果我们的索引中只有member_id字段,那么还需要回表查询order_id和status数据才能返回结果,如果建一个member_id+order_id+status的组合索引:

  1. create index idx_2 on order(member_id,order_id,status);
  1. create index idx_2 on order(member_id,order_id,status);

那只要访问索引就可以返回数据了,这种虽然性能提高了,但是由于索引多了字段,因此增加了索引建立成本和索引空间。

SQLServer

SQLServer除了支持组合索引外,还支持Index Include Column特性,Index Include Column是组合索引的一种变种,它的特点是可以指定组合索引中哪些列是排序列,哪些列只是把内容存储在索引中,这个特性不仅可以满足索引覆盖读取,而且可以减少索引对DML的性能影响。语法如:

  1. create index idx_2 on order(member_id) include(order_id,status);
  1. create index idx_2 on order(member_id) include(order_id,status);

其中member_id字段是普通索引列,order_id和status列是内容include列。

普通组合索引数据存储结构示例:
 
Include Column组合索引数据存储结构示例:
 

SQLServer管理器的SQL优化自动索引推荐就经常看到推荐Include Column方式。

MySQL:不支持,只能用组合索引代替
Oracle:不支持,只能用组合索引代替

三、聚集索引(Cluster Index)

数据库通常用两种存储方式,一种是堆表,即表中的数据是基本无序的,像往一个房间(数据块)堆箱子(记录)一样,只要有空间就往里面放,放满了就准备一个新房间再放。

另外一种就是聚集存储,数据按表中一个或几个字段排序存储,如下图所示。

由于要排序,需要索引来保证效率,所以聚集存储和聚集索引存储通常指一个意思。

SQLServer
        如果表没有主键默认为堆表,如果有主键默认为按主键聚集存储。SQLServer支持非主键索引聚集存储,这个特性非常有意义,比如订单表有订单ID(主键)和会员ID,如果按订单ID聚集存储,由于订单ID一般都是随机访问,返回单条记录,所以对按订单ID查询没有什么性能提高。假设需按会员ID查询,一个会员有许多订单,分页一次返回20条,那就需要20次离散数据访问。
如果可以按会员ID聚集存储,那用会员ID查询可能只需要1次离散数据访问就可以,性能可以提升很多,这种方式对订单插入有一些性能影响,如果订单插入不多,按会员查询频繁,那按会员ID建聚集索引给用订单ID聚集效果很好。
MySQL
       MySQL MYISAM存储引擎只支持堆存储,不支持聚集索引。
       MySQL INNODB存储引擎只能按主键聚集,如果没有主键就用一个内部隐藏主键代替。

Oracle
       Oracle默认是堆存储,如果建成索引组织表则按主键聚集存储。Oracle还有一个种更高级的聚集存储,概念叫簇(Cluster),可以定义一个簇对象,然后将一个或多个表按字段顺序聚集的存储在这个簇中,从而实现多个表聚集存储,适用于一些主从表,如订单与订单明细,它们的数据是按关联字段聚集的存储在一个数据块中,订单与订单明细经常一起查询,所以这种逻辑只要读取一次数据块即可,如果用非Cluster,那需要读取多个数据块才OK。

四、VIEW INDEX(视图索引)

在视图上建索引,感觉没有意义,因为视图本身就是一个逻辑的概念,并不存储物理数据,何来索引之说。

SQLServer
支持。视图上建索引首先视图需要绑定架构。视图上需要先建一个唯的聚集索引,把数据持久化,持久化后还可以建其它新的索引,像普通表一样处理了。

视图上建索引可以让数据持久化,一般有两种用途
1. 统计类数据查询性能优化
如经常要做select sum(amount) from t2这样的操作,性能不好优化,并且t表数据变化不多,那么可以建一个视图(注意:需要加上with schemabinding选项):

  1. CREATE VIEW V2
  2. with schemabinding
  3. AS
  4. SELECT     SUM(amount) as sum_amount,COUNT_BIG (*) as cnt
  5. FROM         t2
  1. CREATE VIEW V2
  2. with schemabinding
  3. AS
  4. SELECT SUM(amount) as sum_amount,COUNT_BIG (*) as cnt
  5. FROM t2

然后在这个视图上建一个唯一聚集索引,数据就持久化了。

  1. CREATE UNIQUE CLUSTERED INDEX idx_4 ON V2 (sum_amount)
  1. CREATE UNIQUE CLUSTERED INDEX idx_4 ON V2 (sum_amount)

然后我们用noexpand方式查询v2索引视图,如下:

  1. SELECT  sum_amount FROM  v2 WITH(NOEXPAND)
  1. SELECT sum_amount FROM v2 WITH(NOEXPAND)

性能会非常好,因为视图里只有一行数据,直接读取即可,不需要再从t2全表扫描汇总。

2.自动实现多维度聚集存储
        数据库的表一般只能设计为按一种方式聚集存储(只允许有一个聚集索引),但在实际业务中存在一些多个维度的查询,比如交易表,需要按买家维度查询,也需要按卖家维度查询。普通表只能选择一种,如果要两种维度性能都很好很难,有时只能人工的分为两张表,一张表按买家聚集,一张表按卖家聚集,用程序或触发器维护两张表数据的一致性,这样看起来很别扭。采用视图索引后可以在主表(买家维度表)上建个视图,然后在视图上用卖家维度建聚集索引,以后如果要按买家查询则查询主表,如果按卖家查询才查询索引视图。
这种性能优化方式只是一个方案设计,实践中没有经过验证。

MySQL:不支持
Oracle:不支持,物化视图可以起到类似的作用,并提供了更多的数据同步控制特性。

2013/3/25

我的新浪微博(http://weibo.com/yzsind)

SQLServer索引的四个高级特性的更多相关文章

  1. Java第四次作业——面向对象高级特性(继承和多态)

    Java第四次作业--面向对象高级特性(继承和多态) (一)学习总结 1.学习使用思维导图对Java面向对象编程的知识点(封装.继承和多态)进行总结. 2.阅读下面程序,分析是否能编译通过?如果不能, ...

  2. Java第四次作业,面向对象高级特性(继承和多态)

    Java第四次作业-面向对象高级特性(继承和多态) (一)学习总结 1.学习使用思维导图对Java面向对象编程的知识点(封装.继承和多态)进行总结. 2.阅读下面程序,分析是否能编译通过?如果不能,说 ...

  3. Java第四次作业—面向对象高级特性(继承和多态)

    Java第四次作业-面向对象高级特性(继承和多态) (一)学习总结 1.学习使用思维导图对Java面向对象编程的知识点(封装.继承和多态)进行总结. 2.阅读下面程序,分析是否能编译通过?如果不能,说 ...

  4. Python进阶:全面解读高级特性之切片!

    导读:切片系列文章连续写了三篇,本文是对它们做的汇总.为什么要把序列文章合并呢?在此说明一下,本文绝不是简单地将它们做了合并,主要是修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章节衔 ...

  5. JavaScript高级特性-数组

    1. JavaScript中的数组 在C++.Java中,数组是一种高效的数据结构,随机访问性能特别好,但是局限性也特别明显,就是数组中存放的数据必须是同一类型的,而在JavaScript中,数组中的 ...

  6. python高级特性:切片/迭代/列表生成式/生成器

    廖雪峰老师的教程上学来的,地址:python高级特性 下面以几个具体示例演示用法: 一.切片 1.1 利用切片实现trim def trim(s): while s[:1] == " &qu ...

  7. InnoDB存储引擎的高级特性大盘点

    InnoDB作为mysql数据库最常用的存储引擎,自然包含了其独有的很多特性.如相比于memory.MyISAM引擎,InnoDB支持行级锁.事务等都是比较重要的特性. 本文将盘点下InnoDB处理事 ...

  8. 云端卫士实战录 | Java高级特性之多线程

    <实战录>导语 一转眼作为一名Java开发者已经四年多时间了,说长不长说短不短,对于java的感情还是比较深的,主要嘛毕竟它给了我饭吃.哈哈,开个玩笑.今天我想借此机会来和大家聊聊Java ...

  9. 解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)

    解剖SQLSERVER 第十四篇    Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...

随机推荐

  1. opencv——基础篇

    一 . opencv是什么及其作用? OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.Android和Mac OS操作系统上.它轻量级而且高效— ...

  2. JavaScript——问卷星自动填写

    一.前言: 我们学校要刷学术章,有些学术章又是指定在某个时间点填写问卷星的问卷报名的.但是由于我手速慢,导致总会有些时候报不上名,于是想着搞个代码实现自动填写问卷星的报名表.一顿操作后,在github ...

  3. Spring Cloud高级视频

    Spring Cloud高级视频 第一章 微服务架构概述 第二章 开始使用Spring Cloud实战微服务 第三章 服务提供者与服务消费者 第四章 服务发现与服务注册 第五章 使用Hystrix保护 ...

  4. HTML_案例(首页制作)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. mysql tar安装模式

    mysql解压版安装过程,之前安装mysql一直用linux yum和rpm方式.今天试了下tar包方式有点麻烦记录下1.安装lrzsz-0.12.20-27.1.el6.x86_64.rpm方便操作 ...

  6. python包的安装

    Microsoft Windows [版本 10.0.17134.228] (c) 2018 Microsoft Corporation.保留所有权利. C:\Users\Administrator& ...

  7. innodb_file_per_table 理解

    MYSQL innodb存储引擎 默认将所有的数据库 innodb 引擎的表数据存储在一个共享空间中:ibdata1,当增删数据库的时候, ibdata1文件不会自动收缩,单个数据库的备份也会成为问题 ...

  8. [转]springmvc+mybatis需要的jar包与详解

    1.antlr-2.7.6.jar:  项目中没有添加,hibernate不会执行hql语句 2.Aopalliance.jar: 这个包是AOP联盟的API包,里面包含了针对面向切面的接口,通常Sp ...

  9. 【JZOJ6354】最短路(tiring)

    description analysis 显然边权有变化规律\(x,{1\over{x-1}},{x-1\over x},x,...\) 于是把一个点拆成三个点,分别表示步数到除\(3\)余\(0,1 ...

  10. 组合数学——cf1065E

    从两端到中间分段,然后累乘即可 #include<bits/stdc++.h> using namespace std; #define mod 998244353 #define max ...