第十章——维护索引(8)——在计算列中创建索引提高性能
前言:
在理解计算列上的索引之前,先了解计算列的基本知识。计算列由可以使用同一表中的其他列的表达式计算得来。表达式可以是非计算列的列名、常量、函数,也可以是用一个或多个运算符连接的上述元素的任意组合。表达式不能为子查询。
默认情况下,计算列是一个虚拟的列,并且可以在调用时重新计算,直到在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)——在计算列中创建索引提高性能相关推荐
- 尽量使用覆盖索引,避免select * || 用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到|| 如果MySQL评估使用索引比全表更慢,则不使用索引
尽量使用覆盖索引,避免select * 尽量使用覆盖索引(只访问索引的查询(索引列完全包含查询列)),减少select * 7). 用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索 ...
- 数据库索引统计信息不一致_列存储索引增强功能–克隆数据库中的索引统计信息更新
数据库索引统计信息不一致 SQL Server was launched in 1993 on WinNT and it completed its 25-year anniversary recen ...
- 索引的作用和为什么要创建索引
为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能. 第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性. 第二,可以大大加快 数据的检索速度,这也是创建索引的最主要的原因. ...
- oracle创建索引占用表空间吗,oracle创建索引表空间
或者 drop tablespace 表空间名称 including contents;(表空间下有数据时候用) temporary tablespace 是 oracle 里临时表空间,临时表空间主 ...
- 如何在不停机的情况下在Django中创建索引
该框架在管理数据库更改方面非常强大和有用,但是该框架提供的灵活性受到了一定的限制.为了理解Django迁移的局限性,你将处理一个众所周知的问题: 在不停机的情况下,在Django中创建一个索引. 在本 ...
- oracle 索引快速全扫描,oracle中的索引扫描
一.INDEX UNIQUE SCAN(索引唯一扫描) 索引唯一性扫描(INDEX UNIQUE SCAN)是针对唯一性索引(UNIQUE INDEX)的扫描,它仅仅适用于where条件里是等值查询的 ...
- oracle不适合建立索引的场景,Oracle 分区表中本地索引和全局索引的适用场景
背景 分区表创建好了之后,如果需要最大化分区表的性能就需要结合索引的使用,分区表有两种索引:本地索引和全局索引.既然存在着两种的索引类型,相信存在即合理.既然存在就会有存在的原因,也就是在特定的场景中 ...
- MySQL数据库索引:删除、查看、创建索引
索引(index)是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息.--百度百科 正常的一张表,是无序,如果要进行查询(select)操作,理论上会将表中所有记录 ...
- pandas中dataframe索引排序实战:pandas中dataframe索引降序排序、pandas中dataframe索引升序排序
pandas中dataframe索引排序实战:pandas中dataframe索引降序排序.pandas中dataframe索引升序排序 目录
最新文章
- 所有雷电接口电脑5分钟内即可破解,漏洞无法软件修复,微软Surface笑了
- 使用R语言绘制层次聚类热图
- freebsd 手工安装zabbix2.0 php,zabbix 服务端,子客户端安装配置日志
- 送卡神算法力作《代码随想录》!
- Android开发者指南(4) —— Application Fundamentals(二)
- VS2019编译 当前最新版chromium
- 如何手动输入给数组赋值_你是否真的了解VBA数组呢?让我带你认识一下真正的数组...
- 阿里年薪40万老人简历:83岁精通网购,62岁会H5、PS
- comparator 字符串比较大小_java – 如何使用Comparator比较空值?
- u-boot2010.06移植阶段三--norflash驱动
- 抓包工具tcpdump的使用总结(持续更新)
- 解决DOS窗口中文乱码问题
- 计算机病毒是计算机软件出现的故障,计算机病毒引发故障有哪些
- 安装sql server2012报错
- 华为USG防火墙NAT
- 同程艺龙解除合作,同程支付艺龙3000万补偿金
- OpenShift免费空间申请使用教程
- requested an insecure resource的解决方法
- 家庭局域网_组建家庭无线局域网需要哪些硬件设备?
- 【牛客网-前端笔试题】——vue专项练习