前言:

在理解计算列上的索引之前,先了解计算列的基本知识。计算列由可以使用同一表中的其他列的表达式计算得来。表达式可以是非计算列的列名、常量、函数,也可以是用一个或多个运算符连接的上述元素的任意组合。表达式不能为子查询。

默认情况下,计算列是一个虚拟的列,并且可以在调用时重新计算,直到在CREATE TABLE或者ALTER TABLE 命令中使用PERSISTED。

如果列定义成PERSISTED,会存放计算值,并存放在原始列上更新后的汇总值,不能对计算列进行INSERT、UPDATE。

准备工作:

首先要了解是否有需要在计算列上创建索引,计算列在下面情况可以考虑创建索引:

1、 如果计算列的数据来源于IMAGE,TEXT和NTEXT数据类型,只能作为非聚集索引的部分列。

2、 计算列表达式不能是REAL或者FLOAT数据类型。

3、 计算列必须明确。

4、 计算列必须具有稳定性。可以使用COLUMNPROPERTY函数的IsDeterministic属性来判断是否稳定。

5、 如果函数使用了任何函数,不管是自定义还是系统内置的,那么表和函数的拥有者必须是相同的。

6、 不能用于通过聚集函数获得的函数值上的列。

7、 需要开启下面的配置:

1、 ARITHABORT

2、 CONCAT_NULL_YIELDS_NULL

3、 QUOTED_IDENTIFIER

4、 ANSI_WARNINGS

5、 ANSI_NULLS

6、 ANSI_PADDING

7、 NUMERIC_ROUNDABORT——OFF,其他为ON 。

步骤:

1、 创建一个测试表:

 USE AdventureWorks2012
GO
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET ARITHABORT ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON
SET NUMERIC_ROUNDABORT OFFSELECT  salesorderid ,salesorderdetailid ,carriertrackingnumber ,orderqty ,productid ,specialofferid ,unitprice
INTO    salesorderdetaildemo
FROM    AdventureWorks2012.sales.salesorderdetail
go

2、 现在创建一个用于计算列的自定义函数,并添加计算列NetPrice到新表中,这个列通过自定义函数UDFTotalAmount来计算值:

 CREATE FUNCTION dbo.UDFTotalAmount(@TotalPrice NUMERIC(10, 3) ,@Freight TINYINT)
RETURNS NUMERIC(10, 3)WITH SCHEMABINDING
ASBEGINDECLARE @NetPrice NUMERIC(10, 3)SET @NetPrice = @TotalPrice +( @totalprice * @Freight / 100 )RETURN @NetPriceEND
GO--添加计算列:
ALTER TABLE SalesOrderDetailDemo ADD [NetPrice] AS
dbo.UDFTotalAmount(OrderQty*UnitPrice,5)
GO

3、 现在在表上创建一个聚集索引。使得表不会再是堆表,然后按照前面说的,修改相关的SET选项,然后开启STATISTICS,记住目前没有创建任何索引在计算列上:

 --创建聚集索引
CREATE CLUSTERED INDEX idx_SalesOrderID_SalesOrderDetailID_SalesOrderDetailDemo ON
SalesOrderDetailDemo(SalesOrderID,SalesOrderDetailID)
GO--开启统计数据
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO--执行查询
SELECT  *
FROM    SalesOrderDetailDemo
WHERE   NetPrice > 5000
GO

得到结果:

SQL Server 分析和编译时间:

CPU 时间= 920 毫秒,占用时间= 967 毫秒。

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 5 毫秒。

(3864 行受影响)

表'salesorderdetaildemo'。扫描计数1,逻辑读取757 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

SQL Server 执行时间:

CPU 时间= 780 毫秒,占用时间= 1643 毫秒。

4、 在创建索引到计算列前,先检查是否符合创建条件:

SELECT  COLUMNPROPERTY(OBJECT_ID('SalesOrderDetailDemo'), 'NetPrice','IsIndexable') AS 'Indexable?' ,COLUMNPROPERTY(OBJECT_ID('SalesOrderDetailDemo'), 'NetPrice','IsDeterministic') AS 'Deterministic?' ,OBJECTPROPERTY(OBJECT_ID('UDFTotalAmount'), 'IsDeterministic') ,'UDFDeterministic?' ,COLUMNPROPERTY(OBJECT_ID('SalesOrderDetailDemo'), 'NetPrice','IsPrecise') AS 'Precise?'

5、 现在在计算列上创建索引,如果你前面说的条件都满足,那么可以创建了:

CREATE INDEX idx_SalesOrderDetailDemo_NetPrice
ON SalesOrderDetailDemo(NetPrice)
GO

然后再次执行查询:

SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
SELECT  *
FROM    SalesOrderDetailDemo
WHERE   NetPrice > 5000
GO

6、 结果如下:

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 0 毫秒。

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 0 毫秒。

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 3 毫秒。

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 0 毫秒。

(3864 行受影响)

表'salesorderdetaildemo'。扫描计数1,逻辑读取757 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

SQL Server 执行时间:

CPU 时间= 780 毫秒,占用时间= 1534 毫秒。

分析:

在计算列创建一个索引,存储键值到叶子节点并在SELECT的时候利用索引的统计信息,在大部分的情况下是工作得很好的。但是也有很多情况下不能用计算列。

在统计数据上,可以看到SQLServer Parse和Compile 时间还有SQLServer执行时间。如果数据量很大,那么创建了索引在计算列上的效能提高将会很明显。

第十章——维护索引(8)——在计算列中创建索引提高性能相关推荐

  1. 尽量使用覆盖索引,避免select * || 用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到|| 如果MySQL评估使用索引比全表更慢,则不使用索引

    尽量使用覆盖索引,避免select * 尽量使用覆盖索引(只访问索引的查询(索引列完全包含查询列)),减少select * 7). 用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索 ...

  2. 数据库索引统计信息不一致_列存储索引增强功能–克隆数据库中的索引统计信息更新

    数据库索引统计信息不一致 SQL Server was launched in 1993 on WinNT and it completed its 25-year anniversary recen ...

  3. 索引的作用和为什么要创建索引

    为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能.  第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性.  第二,可以大大加快 数据的检索速度,这也是创建索引的最主要的原因. ...

  4. oracle创建索引占用表空间吗,oracle创建索引表空间

    或者 drop tablespace 表空间名称 including contents;(表空间下有数据时候用) temporary tablespace 是 oracle 里临时表空间,临时表空间主 ...

  5. 如何在不停机的情况下在Django中创建索引

    该框架在管理数据库更改方面非常强大和有用,但是该框架提供的灵活性受到了一定的限制.为了理解Django迁移的局限性,你将处理一个众所周知的问题: 在不停机的情况下,在Django中创建一个索引. 在本 ...

  6. oracle 索引快速全扫描,oracle中的索引扫描

    一.INDEX UNIQUE SCAN(索引唯一扫描) 索引唯一性扫描(INDEX UNIQUE SCAN)是针对唯一性索引(UNIQUE INDEX)的扫描,它仅仅适用于where条件里是等值查询的 ...

  7. oracle不适合建立索引的场景,Oracle 分区表中本地索引和全局索引的适用场景

    背景 分区表创建好了之后,如果需要最大化分区表的性能就需要结合索引的使用,分区表有两种索引:本地索引和全局索引.既然存在着两种的索引类型,相信存在即合理.既然存在就会有存在的原因,也就是在特定的场景中 ...

  8. MySQL数据库索引:删除、查看、创建索引

    索引(index)是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息.--百度百科 正常的一张表,是无序,如果要进行查询(select)操作,理论上会将表中所有记录 ...

  9. pandas中dataframe索引排序实战:pandas中dataframe索引降序排序、pandas中dataframe索引升序排序

    pandas中dataframe索引排序实战:pandas中dataframe索引降序排序.pandas中dataframe索引升序排序 目录

最新文章

  1. 所有雷电接口电脑5分钟内即可破解,漏洞无法软件修复,微软Surface笑了
  2. 使用R语言绘制层次聚类热图
  3. freebsd 手工安装zabbix2.0 php,zabbix 服务端,子客户端安装配置日志
  4. 送卡神算法力作《代码随想录》!
  5. Android开发者指南(4) —— Application Fundamentals(二)
  6. VS2019编译 当前最新版chromium
  7. 如何手动输入给数组赋值_你是否真的了解VBA数组呢?让我带你认识一下真正的数组...
  8. 阿里年薪40万老人简历:83岁精通网购,62岁会H5、PS
  9. comparator 字符串比较大小_java – 如何使用Comparator比较空值?
  10. u-boot2010.06移植阶段三--norflash驱动
  11. 抓包工具tcpdump的使用总结(持续更新)
  12. 解决DOS窗口中文乱码问题
  13. 计算机病毒是计算机软件出现的故障,计算机病毒引发故障有哪些
  14. 安装sql server2012报错
  15. 华为USG防火墙NAT
  16. 同程艺龙解除合作,同程支付艺龙3000万补偿金
  17. OpenShift免费空间申请使用教程
  18. requested an insecure resource的解决方法
  19. 家庭局域网_组建家庭无线局域网需要哪些硬件设备?
  20. 【牛客网-前端笔试题】——vue专项练习

热门文章

  1. Java网编之:Socket套接字
  2. 解决html页面中文乱码
  3. matlab2012a到期重新激活
  4. C++ 数据结构(三)列表(3)有序列表
  5. HINSTANCE/HWND/CWnd/HANDLE 的区别
  6. 2021年我国热泵市场规模、产值及进出口分析[图]
  7. 华硕dhd24简单分析硬件检测思路
  8. 个人对23种设计模式总结 优缺点分析
  9. 数据库函数依赖与候选码求解
  10. python多维字典_python定义多维字典