- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章解析SQL Server聚焦移除(Bookmark Lookup、RID Lookup、Key Lookup)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
前面几节都是讲的基础内容,本节我们讲讲索引性能优化,当对大数据进行处理时首先想到的就是索引,一旦遇到这样的问题则手忙脚乱,各种查资料,为何平常不扎实基本功呢,我们由浅入深,简短的内容,深入的理解,而非一上来就把问题给框死,立马给出解决方案,抛出问题,再到解决问题,你GET了没有.
Bookmark Lookup、RID Lookup、Key Lookup定义 。
一说到这三者,如果对索引研究不深的童鞋估计是懵逼的,什么玩意,我们姑且将上面三者翻译为:标签查找、行ID查找、键查找。标签查找和键查找是一个意思,在SQL 2005之前叫Key Lookup。怎么解释,如何定义呢?首先我们不看定义,直接看下面一步一步解析,如果你实在忍不住,请看园友【永红】的见解,解释还是非常到位。我们简短的说明下此三者概念.
在查询中,我们对返回的列在查询条件上若建立了非聚集索引,此时将可能尝试使用非聚集索引查找,如果返回的列没有创建非聚集索引,此时会返回到数据页中去获取这些列的数据,即使表中存在聚集索引或者没有,都会返回到表中或者聚集索引中去获取数据。对于以上场景描述,如果表没有创建聚集索引则称为Bookmar Lookup,如果表中没有聚集索引但是存在非聚集索引我们称为RID Lookup。看到这里我们就会想法操作如此耗时,还要返回到基表中去获取数据,所以才有了我们本节来移除以上三者来提高查询性能。接下来我们一起来看看.
抛出Bookmark Lookup、RID Lookup、Key Lookup问题 。
我们首先创建如下表 。
1
2
3
4
5
6
7
8
9
|
USE TSQL2012
GO
CREATE
TABLE
Sales.Orders
(
[orderid]
INT
,
[shipaddress]
VARCHAR
(100),
[shipcity]
VARCHAR
(100),
[shipregion]
VARCHAR
(100))
GO
|
接着进行查询 。
1
2
3
4
5
|
USE TSQL2012
GO
SELECT
orderid, shipaddress, shipregion
FROM
Sales.Orders
WHERE
shipcity =
'深圳'
|
这个不用多讲,没添加任何索引,执行查询计划是全表扫描。接下来我们创建在orderid上创建聚集索引如下:
CREATE CLUSTERED INDEX idx_cls_orderid ON Sales.Orders(orderid) 。
我们再执行上述查询 。
此时我们创建了聚集索引,所以此时查询走聚集索引,到这里我们看到情况由全表扫描转换成了索引扫描。我们在查询时一直是带了查询条件的,而对查询条件我们未作任何操作,如果我们此时在查询条件上创建了索引,此时查询的性能又会得到一点改善。我们开始对查询条件创建一个非聚集索引.
CREATE NONCLUSTERED INDEX idx_nc_shipcity ON Sales.Orders(shipcity) 。
我们再接着执行查询 。
我们观察到对查询条件创建了非聚集索引,查询计划会使用非聚集索引查找返回结果,但是对于shipaddress, shipcity, shipregion并不是索引的一部分,此时查询引擎会返回到基表中得到这些数据再返回。这种行为就叫做Bookmark Lookup或者Key Lookup。下面我们就如本文标题一样问题出现来解决问题,移除Bookmark Lookup或者Key Lookup。我们尝试用两种不同的方法来解决.
解决Bookmark Lookup、RID Lookup、Key Lookup问题 。
创建非聚集索引覆盖索引 。
我们对查询条件以及检索列创建非聚集索引.
CREATE NONCLUSTERED INDEX idx_all_cover ON Sales.Orders(shipaddress,orderid,shipcity,shipregion) 。
此时我们对检索列创建了非聚集索引,此时将不会再到数据页中获取数据,而是从索引中直接返回,所以到这里我们算是移除了Key Lookup。但是此时触发另外一个问题,执行查询计划走的却是索引扫描,索引到底是什么呢?我们打个比方,一个索引相当于是数据库中一个本书开始的索引,我们需要快速从书中查找到我们所需要的数据,这个时候书就是我们所说的表。索引扫描意味着要读取表中的所有行,然后返回满足条件的所有数据,当执行索引扫描时,所有行上叶子节点上的所有都会被扫描,这也就意味着索引上的所有行都会被检索一遍而不是直接检索表,和表扫描对比的话,表扫描是直接读取表中数据,所以表扫描和索引扫描还是有一点点不同,而索引查找则是依赖于索引页数据来定位满足条件的所有行,索引查找仅仅只影响满足条件以及页上包含这些满足条件的行,所以说索引查找更加高效.
上述我们稍微讲解了下索引扫描和索引查找,而上述的问题是我们创建了非聚集索引,但是结果执行的查询计划是索引扫描,很是纳闷,对于刚学索引小白的我来说,不知该如何是好,以为是缓存的缘故,清除各种缓存均不好使。于是开始胡思乱想是不是检索列中数据有为NULL引起的,是不是检索列数据重复引起的,尝试了无数次,最终发现某一次居然好使。如下 。
1
2
|
CREATE
NONCLUSTERED
INDEX
idx_cls_cover
ON
Sales.Orders(shipcity,orderid,shipaddress,shipregion)
|
此时若我们将查询条件进行如下修改.
1
2
3
4
5
6
|
USE TSQL2012
GO
SELECT
orderid, shipaddress, shipregion
FROM
Sales.Orders
WHERE
shipaddress =
'深圳'
GO
|
到这里我们应该发现了,唯一的区别在于我们创建非聚集索引时的顺序和查询条件不同就会导致索引扫描和索引查找的转换,那么到底什么时候才会执行索引查找呢?我们可以进行如下一般性总结:
索引查找的一般性结论:如果条件中包含WHERE或者ON的话,查询条件必须是位于索引集合列中首位,此时索引查找将会被使用.
此时我们穿插一点内容,上述我们创建了覆盖索引,我们来比较下覆盖索引和默认情况下聚集索引查找的性能开销.
覆盖索引与默认聚集索引性能开销比较 。
1
2
3
4
5
6
7
|
FROM
Sales.Orders
WITH
(
INDEX
([PK_Orders]))
WHERE
orderid<11072
go
SELECT
orderid, shipaddress, shipregion
FROM
Sales.Orders
WITH
(
INDEX
([idx_noncls_include_exceptorderid]))
WHERE
orderid<11072
GO
|
从上可知,覆盖索引的开销要比默认主键聚集索引性能开销要好一点,同时我们可以看看如下二者IO代价.
通过上述覆盖索引与默认聚集索引的对比,我们能够有效的减少IO,这一点也是非常明确的,当然下面的INCLUDE索引对比也是另外一种好的方案.
创建INCLUDE非聚集索引 。
1
2
3
4
5
|
USE TSQL2012
GO
CREATE
NONCLUSTERED
INDEX
[ix_noncls_include]
ON
[TSQL2012].[Sales].[Orders] (
shipcity
) INCLUDE (shipaddress, shipregion, orderid)
|
至此我们用两种方式来移除了Bookmark Lookup、RID Lookup、Key Lookup,通过使用索引和覆盖索引.
既然有如上两种方式,我们应该有所取舍,二者谁的性能更好呢?我们接下来比较上述二者的开销差异.
比较移除Bookmark Lookup等两种方式差异 。
1
2
3
4
5
6
7
8
9
10
|
USE TSQL2012
GO
SELECT
orderid, shipaddress, shipcity, shipregion
FROM
Sales.Orders
WITH
(
INDEX
(idx_all_cover))
WHERE
shipcity =
'深圳'
GO
SELECT
orderid, shipaddress, shipcity, shipregion
FROM
Sales.Orders
WITH
(
INDEX
(ix_noncls_include))
WHERE
shipcity =
'深圳'
GO
|
我们从上所知,二者开销一样,并未有什么区别,当然相信我们更倾向于的是将第二种方式作为解决方案。到这里算是基本结束了,但是还有一个小问题,我们在之前已经创建了orderid的聚集索引,后面在解决方案中我们也添加了orderid的非聚集索引,难道非得添加吗,我们去掉试试看.
1
2
3
4
|
CREATE
NONCLUSTERED
INDEX
idx_noncls_cover_exceptorderid
ON
Sales.Orders(shipcity,shipaddress,shipregion)
CREATE
NONCLUSTERED
INDEX
idx_noncls_include_exceptorderid
ON
Sales.Orders(shipcity) INCLUDE(shipaddress,shipregion)
|
去除orderid比较二者开销差异:
1
2
3
4
5
6
7
8
9
10
|
USE TSQL2012
GO
SELECT
orderid, shipaddress, shipregion
FROM
Sales.Orders
WITH
(
INDEX
([idx_noncls_cover_exceptorderid]))
WHERE
shipaddress =
'深圳'
GO
SELECT
orderid, shipaddress, shipregion
FROM
Sales.Orders
WITH
(
INDEX
([idx_noncls_include_exceptorderid]))
WHERE
shipaddress =
'深圳'
GO
|
由上知,非聚集索引列不需要包含创建了聚集索引的列,那么事实到底是怎样的呢?
结论:其实对于任何非聚集索引列都不需要包含创建了聚集索引的列,因为创建聚集索引的列是非聚集索引集合列的一部分,也就是说只要一个表上的列创建了聚集索引,那么非聚集索引集合列就包含了这个聚集索引.
总结 。
本节我们比较详细就问题的抛出到问题的解决,从而来提高查询性能,好了,到此结束,我们下节再会。简短的内容,深入的理解 。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,同时也希望多多支持我! 。
原文链接:http://www.cnblogs.com/CreateMyself/p/6117352.html 。
最后此篇关于解析SQL Server聚焦移除(Bookmark Lookup、RID Lookup、Key Lookup)的文章就讲到这里了,如果你想了解更多关于解析SQL Server聚焦移除(Bookmark Lookup、RID Lookup、Key Lookup)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
本周我将在 Windows Server 2008 上设置一个专用的 SQL Server 2005 机器,并希望将其精简为尽可能简单,同时仍能发挥全部功能。 为此,“服务器核心”选项听起来很有吸引力
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 8 年前。 Improve
我获取了 2014 版本数据库的备份,并尝试在另一台服务器中将其恢复到具有相同名称和登录名的数据库中。此 SQL Server 版本是 2016。 恢复备份文件时,出现此错误: TITLE: Micr
我获取了 2014 版本数据库的备份,并尝试在另一台服务器中将其恢复到具有相同名称和登录名的数据库中。此 SQL Server 版本是 2016。 恢复备份文件时,出现此错误: TITLE: Micr
TFS 是否提供任何增强的方法来存储对 sql server 数据库所做的更改,而不是使用它来对在数据库上执行的 sql 语句的文本文件进行版本控制? 或者我正在寻找的功能是否仅在第 3 方工具(如
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我即将将我的 SQL Server 2012 实例升级到 SQL Server 2014。 我已经克隆了主机 Windows VM 并将其重命名为 foo-2012至 foo-2014 . 重新启动时
我想为 SQL Server 登录授予对数据库的访问权限。我知道 sp_grantdbaccess,但它已被弃用。我可以改用什么以及如何检查登录名是否还没有访问数据库的权限? 场景:UserA 创建数
客户别无选择,只能在接下来的几天内从 sql server 2000 迁移到 2008。测试显示 2005 年的重要功能出现了 Not Acceptable 性能下降,但 2008 年却没有。好消息是
我有一个测试数据库,我需要将其导出到我们客户的测试环境中。 这将是一次性的工作。 我正在使用 SQL Server 2005(我的测试数据库是 SQL Server 2005 Express) 执行此
我需要将一个 CSV 文件导入到 mongoDB 不幸的是我遇到了以下错误: error connecting to host: could not connect to server: se
我以为 R2 是一个补丁/服务包。我一直在寻找下载,但没有看到。因此,我假设 R2 是一个新版本,并且我需要 sqlserver 2008 r2 的安装介质来进行升级? 另外,我需要为新许可证付费吗?
我无法使用 SQL Server Management Studio 连接到 SQL Server。 我有一个连接字符串: 我尝试通过在服务器名中输入 myIP、在登录名中输入 MyID、在密码中
我们希望使用 SQL Server 加密来加密数据库中的几个列。我们还需要在生产和测试环境之间传输数据。看来最好的解决方案是在生产和测试服务器上使用相同的主 key 、证书和对称 key ,以便我可以
有没有可以分析 SQL Server 数据库潜在问题的工具? 例如: a foreign key column that is not indexed 没有 FILL FACTOR 的 uniquei
我正在尝试从我的 SQL 2012 BI 版本建立复制,但我收到一条奇怪的错误消息! "You cannot create a publication from server 'X' because
如果您使用 SQL Server 身份验证 (2005),登录详细信息是否以明文形式通过网络发送? 最佳答案 如您所愿,安全无忧... 您可以相当轻松地配置 SSL,如果您没有受信任的证书,如果您强制
我想将数据从一个表复制到不同服务器之间的另一个表。 如果是在同一服务器和不同的数据库中,我使用了以下 SELECT * INTO DB1..TBL1 FROM DB2..TBL1 (to copy w
我希望得到一些帮助,因为我在这个问题上已经被困了 2 天了! 场景:我可以从我的开发计算机(和其他同事)连接到 SERVER\INSTANCE,但无法从另一个 SQL Server 连接。我得到的错误
我正在尝试从我的 SQL 2012 BI 版本建立复制,但我收到一条奇怪的错误消息! "You cannot create a publication from server 'X' because
我是一名优秀的程序员,十分优秀!