如果一张表上没有聚集索引,数据将会随机的顺序存放在表里。以dbo.SalesOrderDetail_TEST为例子。它的上面没有聚集索引,只有一个在SalesOrderID上的非聚集索引。所以表格的每一行记录,不会按照任何顺序,而是随意地存放在Hash里。这个时候如果用户想要找所有单价大于200的销售详细记录,要运行的语句会是:

SET STATISTICS  PROFILE ON 

SELECT SalesOrderDetailID , Unitprice
FROM SalesOrderDetail_test
WHERE UnitPrice > 200

由于表在UnitPrice上没有索引,所以SQL SERVER不得不对这个表从头到尾扫描一遍,把所有UnitPrice的值大于200的记录一个一个挑出来。

从执行计划里可以清楚地看出来SQL SERVER 这里做了一个表扫描(下图),后面会详细介绍如何得到和分析执行计划

如果这个表上有聚集索引,事情会怎么样呢?还是刚才那张表做例子,先给它的值是唯一的字段 Unitprice上建立一个聚集索引。这样所有的数据都会按照聚集索引的顺序存储。

CREATE CLUSTERED INDEX  SalesOrderDetail_TEST_CL ON dbo.SalesOrderDetail_test (SalesOrderDetailID)

可惜的是,查询条件Unitprice上没有索引,所以SQL SERVER还是要把所有记录都扫描一遍。如下图

与之前不同的是,执行计划里的表扫描变成了聚集索引扫描。因为在有聚集索引的表上,数据是直接存放在索引的最底层的,所以要扫描整个表格的数据,就是把整个聚集索引扫描一遍。在这里,聚集索引扫描就相当于一个表扫描。所要用的时间和资源与表扫描没有什么差别。并不是说这里有了”Index”这个字样,就说明执行计划比表扫描的有多大进步。当然反过来讲,如果看到”Table Scan”的字样,就说明这个表格上没有聚集索引。

现在在 UnitPrice 上面建一个非聚集索引,看看情况会有什么变化

CREATE NONCLUSTERED INDEX  SalesOrderDetail_TEST_NCL_Price ON dbo.SalesOrderDetail_test (UnitPrice)

再次查询

SET STATISTICS  PROFILE ON 

SELECT SalesOrderDetailID , Unitprice
FROM SalesOrderDetail_test
WHERE UnitPrice > 200

在非聚集索引里,会为每条记录存储一份非聚集索引索引键的值和一份聚集索引索引键的值(在没有聚集索引的表格里,是RID值)。所以在这里,每条记录都会有一份 SalesOrderDetailID和UnitPrice记录,按照UnitPrice的顺序存放。再查询,就会看到这次的SQL SERVER不是扫描整个表,会根据新建的索引直接找到符合的记录的值。

但是光用UnitPrice建立在上的索引不能告诉我们其它字段的值。如果在刚才那个查询里再增加几个字段返回,SQL SERVER 就要先在非聚集索引上找到所有UnitPrice大于200的记录,然后再根据SalesOrderDetailID的值找到存储在聚集索引上的详细数据。这个过程可以称为 “Bookmark Loopup”

SET STATISTICS  PROFILE ON

SELECT SalesOrderId,SalesOrderDetailID , Unitprice
FROM SalesOrderDetail_test with(index = SalesOrderDetail_TEST_NCL_Price)
WHERE UnitPrice > 200

在SQL SERVER 2005以后,Bookmark Loopup 的动作用一个嵌套循环来完成。所以在执行计划里,可以看到SQL SERVR是先SEEK了非聚集索引,然后再用Clustered Index Seek 把需要的行找出来。这里的嵌套循环其实就是 Bookmark Loopup 如下图。

注:Bookmark Loopup就是聚集索引

在SQL SERVER里根据数据找寻目标的不同和方法不同。有下面几种情况。

结构

Scan

Seek

堆(没有聚集索引的表)

Tablescan

聚集索引

Clustered Index Scan

Clustered Index Seek

非聚集索引

Index Scan

Index Seek

如果在执行计划里看到这些动作,就应该能够知道SQL SERVER正在对哪种对象在做什么样的操作。表扫描表明正在处理的表没有聚集索引,SQL SERVER正在扫描整张表。聚集索引扫描表明SQL SERVER正在扫描一张有聚集索引的表,但是也会是整表扫描。Index Scan表明SQL SERVER正在扫描一个非聚集索引。由于非聚集索引上一般只会有一小部分字段,所以这些虽然也是扫描,但是代价会比整表扫描要小很多。Clustered Index Seek 和Index Seek会比Scan 说明SQL SERVER正在利用索引结果检索目标数据。如果结果集只占表格总数据量的一小部分,Seek 会比Scan便宜很多,索引就起到了提高性能的作用。

了解这些是为以后读懂执行计划做基础。水平有限,暂时为这些吧。大家可以多多交流。

下一次会写统计信息的东西,可能会稍多一些。上述一语句均为上一次发博客的脚本为例。

SQL语句调优 - 索引上的数据检索方法的更多相关文章

  1. SQL语句调优-基础知识准备

    当确定了应用性能问题可以归结到某一个,或者几个耗时资源的语句后,对这些语句进行调优,就是数据库管理员或者数据库应用程序开发者当仁不让的职责了.语句调优是和数据库打交道的必备基本功之一. 当你面对一个“ ...

  2. MySQL千万级多表关联SQL语句调优

    本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化.   需要优化的查询:使用explain      出现了Using temporary:       ...

  3. MySQL百万级、千万级数据多表关联SQL语句调优

    本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化,使百万级.千万级数据表关联查询第一页结果能在2秒内完成(真实业务告警系统优化结果).希望读者能够理解S ...

  4. SQL语句调优三板斧

    改装有顺序------常开的爱车下手 你的系统中有成千上万的语句,那么优化语句从何入手呢 ? 当然是系统中运行最频繁,最核心的语句了.废话不多说,上例子: 这是一天的语句执行情况,里面柱状图表示的是对 ...

  5. SQL语句调优相关方法

    SQL语句慢的原因:1,数据库表的统计信息不完整2,like查询估计不准确调优方法:1,查看表中数据的条数:2, explain analyze target_SQL;查看SQL执行计划:比较SQL总 ...

  6. SQL语句调优 - 统计信息的含义与作用及维护计算

    统计信息的含义与作用                                                                                          ...

  7. SQL语句调优汇总

    1.插入数据的表或临时表,预先创建好表结构,能够加快执行速度 2.where 条件判断的字段以及连接查询的条件字段   都添加上索引   能够加快执行速度 3.尽量避免使用 like ,类似 like ...

  8. 【初学Java学习笔记】SQL语句调优

    1, 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2,应尽量避免在 where 子句中对字段进行 null 值判断,创建表时NULL是默认 ...

  9. SQL 语句调优 where 条件 数据类型 临时表 索引

    基本原则 避免全表扫描 建立索引 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理 尽量避免大事务操作,提高系统并发能力 使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方 ...

随机推荐

  1. JS 将字符串转换成日期类型

    将字符串形式的日期转换成日期对象 var strTime="2011-04-16"; //字符串日期格式           var date= new Date(Date.par ...

  2. ASP.NET中的KRE是什么?

    KRE的英文全称是K Runtime Environment,其中K是ASP.NET vNext(后来叫ASP.NET 5)的项目代号. KRE是ASP.NET 5运行时环境,它是ASP.NET 5的 ...

  3. [Hyper-V]给Hyper-V创建两块网卡备用

    描述 给Hyper-V创建两块网卡备用 步骤: 1 打开Hyper-V,在右侧Action栏,单击Virtual Switch Manager… 2 依次选择New Virtual network s ...

  4. 作业七:团队项目——Alpha版本冲刺阶段-02

    昨天进展:框架设计以及菜单设计. 今天安排:完善界面设计以及象棋图片的绘制. 小组一共三人,陈芝航因家里有事,与我们进行了QQ视屏会议.

  5. hibernate懒加载(转载)

    http://blog.csdn.net/sanjy523892105/article/details/7071139 懒加载详解 懒加载为Hibernate中比较常用的特性之一,下面我们详细来了解下 ...

  6. 彻底掌握this,call,apply

    说起js里面比较头疼的知识点,this的指向,call与apply的理解这三者肯定算的上前几,好的js开发者这是必须迈过的槛.今天就总结下这三者紧密相连的关系. 首先推荐理解call的用法 Funct ...

  7. dao层

    /* * 查询 */ public List<User> selectAll(); public User findById(String id); public User findByU ...

  8. 转:最简单的基于 DirectShow 的视频播放器

    50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectSho ...

  9. CMSIS OS None

    /* ---------------------------------------------------------------------- * Copyright (C) 2011 ARM L ...

  10. C#之读取web上的xml

    一.使用LINQ读取使用Xdocument上的Load方法,可以快速的加载一个XML文档,然后使用LINQ对 加载XML文档进行查询或其他操作,这里仅简单偏历.所以,一旦查询一组元素有返回元素集,就可 ...