SQL 查询性能优化 解决书签查找

时间:2024-01-28 08:33:53 

先来看看什么是书签查找:

当优化器所选择的非聚簇索引只包含查询请求的一部分字段时,就需要一个查找(lookup)来检索其他字段来满足请求。对一个有聚簇索引的表来说是一个键查找(key lookup),对一个堆表来说是一个RID查找(RID lookup)。这种查找即是——书签查找。

书签查找根据索引的行 * 从表中读取数据。因此,除了索引页面的逻辑读取外,还需要数据页面的逻辑读取。

从索引的行 * 到从表中读取数据这之间会产生一些额外的开销,本文就来解决这个开销。

先看下我的测试表结构:
SQL 查询性能优化 解决书签查找
其中可以看出 有一个 聚簇索引 PK_UserID 和一个 非聚簇索引IX_UserName。

看看产生书签 查找的效果:

select UserName,Gender from dbo.UserInfo where UserName='userN600'

按上面的 SQL 产生执行计划 可以看出, 会产生一个书签查找(Key Lookup),如下图

SQL 查询性能优化 解决书签查找

如果把上面的 SQL 改写成

select UserName from dbo.UserInfo where UserName='userN600'

SQL 查询性能优化 解决书签查找
可以看出 书签查找 没有了。

本SQL 产生书签查找的 主要原因是 本SQL 优化器会选择 非聚簇索引IX_UserName,来执生SQL 。IX_UserName 索引不包含 Gender 这个字段 于是产生个从索引到 数据表的 一个 查找 即 书签查找。
解决书签查找:

方法一、使用一个 聚簇索引

对于聚簇索引, 索引的叶子页面和表的数据页面相同,因此,当读取聚簇索引 键列的值时,数据引擎可以读取其它列的值而不需要任何行定位,这样就解决了书签查找。
对于这句SQL ( select UserName,Gender from dbo.UserInfo where UserName='userN600')解决了书签查找的办法就是在UserName 上 建聚簇索引 ,因为一个表只有一个聚簇索引 ,这就意味着删除现有聚簇索引(PK_UserID),将会造成其它从表 中的外键约束 要发生更改,这需要考一些相关的工作,可能严重影响依赖于现有聚簇索引的其它查询。

方法二、使用一个 覆盖索引

覆盖索引 是在所有为满足SQL 查询不用到达基本表所需的列 建立的非聚簇索引。如果查询遇到一个索引并且完全不需要引用底层数据表,那么 该索引可以被认为是 覆盖索引。
对于这句SQL ( select UserName,Gender from dbo.UserInfo where UserName='userN600') 解决书签查找的办法就是 在非聚簇索引IX_UserName 里包含 Gender 字段。
也就是在 建索引时 用INCLUDE 语句,具体操作如下
SQL 查询性能优化 解决书签查找
用INCLUDE 最好在 以下情况下使用:
1、不希望增加索引键的大小,但是仍然可以建一个 覆盖索引;
2、打算索引一种不能被索引的数据类型(除了文本、NTEXT和图像);
3、已经超过了一个索引的关键字列的最大数量

方法三、使用 索引连接

索引连接 是使用多个索引之间一个索引交叉来完全覆盖一个查询。如果覆盖索引变的非常宽,那么就可以考虑索引连接。
对于这句SQL ( select UserName,Gender from dbo.UserInfo where UserName='userN600' and Gender=1)可以在 Gender 上 建一个非聚簇索引就行了。
对于这个例 子,可能 SQL 优化器并没有同时 选 用非聚簇索引IX_UserName 和 我们新建立在Gender 上的索引,这时我们可以告知 SQL 优化器 同时使用 这个两上索引,操作如下
select Gender,UserName from UserInfo with(index (IX_Gender,IX_UserName)) where UserName='jins' and Gender=0

好了就写这么多吧.

标签:性能优化,书签查找
0
投稿

猜你喜欢

  • Git命令的简单整理大全

    2023-09-22 09:30:52
  • python常用数据结构元组详解

    2022-08-14 08:14:44
  • django初始化数据库的实例

    2023-09-19 07:35:47
  • asp防止盗链HTTP_REFERER判断代码

    2010-03-12 10:41:00
  • Python实现根据日期获取当天凌晨时间戳的方法示例

    2023-08-04 14:16:46
  • python 递归调用返回None的问题及解决方法

    2022-12-21 05:52:56
  • Python实现简易版的Web服务器(推荐)

    2021-04-21 04:41:15
  • 一起来了解mysql数据库

    2024-01-24 07:40:00
  • MySQL 8.0 之不可见列的基本操作

    2024-01-18 17:32:41
  • 解决Pycharm 导入其他文件夹源码的2种方法

    2023-03-02 08:32:54
  • go特性之数组与切片的问题

    2023-07-15 18:21:30
  • django数据模型on_delete, db_constraint的使用详解

    2023-02-16 04:48:06
  • 如何用C代码给Python写扩展库(Cython)

    2023-06-08 17:06:32
  • python异步任务队列示例

    2021-05-04 03:09:07
  • MySQL中几种数据统计查询的基本使用教程

    2024-01-13 22:29:56
  • ASP程序开发注意的安全事项

    2010-05-03 10:55:00
  • python_tkinter弹出对话框创建2

    2023-10-17 06:27:29
  • PHP安全的URL字符串base64编码和解码

    2023-09-06 22:04:45
  • 简单实现Standby SQL Server 数据库的方法

    2009-10-23 09:26:00
  • 向外扩展SQL Server 实现更高扩展性

    2008-12-18 14:45:00
  • asp之家 网络编程 m.aspxhome.com