蝈蝈俊.net

-- 用随笔来记录自己的技术感触
随笔 - 597, 评论 - 4064, 引用 - 276

导航

关于

这里是我的技术Blog,下一代CSDN社区Blog在 http://blog.csdn.net/ghj1976/

标签

每月存档

最新留言

  • re:学习笔记:7种结构型设计模式简单对比
    <p>最新在家创业系统 ----刚从国外引进,市场巨大。 ----在家可经营所有国家生意,事业规模宏大。 ----不需求人与说服;不用放厚脸皮去推销。 ----极小投资;零风险;成...
    by jackielongteng(注册) on 2009/6/14 13:43:56
  • re:作用域
    <p>☆                    &deg;∵☆       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
    by jackielongteng(注册) on 2009/6/14 13:03:25
  • re:Html标签嵌套对展示性能的影响
    <p><strong>所有的浏览器都按照你提到的浏览器解析Html规则来解析嘛?</strong></p>
    by Cola(注册) on 2009/6/12 23:07:28
  • re:Html5
    <p>目前来说,HTML5还只是一个梦想,呵呵:)</p>
    by 开心就好(注册) on 2009/6/11 16:31:54
  • re:多线程与SqlConnection.Close
    <p>好服月租型IT服务台,与你共成长! 月租型ITSM软件,注册即可免费体验! 详情请登录官方网站:<a href="http://www.servicezon.co...
    by qzhibo(注册) on 2009/6/3 15:14:21
  • re:多线程Singleton单件模式
    <pre><span style="color: #0000ff;">//Another way public</span> <sp...
    by Yaojian(注册) on 2009/4/22 14:02:35
  • re:Thread.Sleep(0)
    <p>学习了~</p>
    by shuitong888(注册) on 2009/4/8 14:29:24
  • re:Html标签嵌套对展示性能的影响
    <p>DIV固然好 但IE6,7,8 firefox,safari ....做美工的人要累死.</p>
    by ryq1(注册) on 2009/4/3 14:16:25
  • re:用.net 编码实现朗读文本的方法
    <p>我第一次 按键时 能听到声音,但是第二次按键时,没反应。网页一直在 loading.&nbsp;是什么原因?</p>
    by tracytang949(注册) on 2009/3/27 7:01:09
  • re:information_schema.routines与sysobjects
    <p>用sys.procedures多好。</p>
    by luke(注册) on 2009/3/16 16:45:49
  • re:SQL Server 2005 配置发送邮件
    <p>&lt;A href="<a href="http://www.3rt.info">http://www.3rt.info</...
    by ives007(注册) on 2009/2/26 16:47:00
  • re:推荐 Gemini 这个bug管理工具
    <p>你好!首先非常感谢推荐使用Gemini,这段时间在使用Gemini,有些问题想请教以下。</p> <p>1.Create Issue 以后,设置了Visib...
    by CowboyRyan(注册) on 2009/2/20 15:45:08
  • re:推荐 Gemini 这个bug管理工具
    <p>你好!首先非常感谢推荐使用Gemini,这段时间在使用Gemini,有些问题想请教以下。</p> <p>1.Create Issue 以后,设置了Visib...
    by CowboyRyan(注册) on 2009/2/20 15:32:06
  • re:虚机搭配NLB负载平衡时碰到"没有接口可用于安装新的群集"的解决方案
    <p>google newsid</p>
    by iads(注册) on 2009/2/13 17:25:07
  • re:try catch 与线程
    <p>确实是这样的。因为异常机制本质上是堆栈操作,而各线程的堆栈是独立的。</p>
    by st_szr(注册) on 2009/1/21 9:46:05
  • re:try catch 与线程
    <p>没啥啊,线程就是新启动了一个,当然异常不会影响到原有的线程了。</p> <p>你应该在线程里面合适的位置写上自己的捕获代码就行了。</p>
    by laozizhu(注册) on 2009/1/19 16:33:21
  • re:我的2008,征服天堂
    <p>蝈蝈,可惜我帮不了你啊!</p>
    by laozizhu(注册) on 2009/1/19 16:25:45
  • re:try catch 与线程
    <p>呃&hellip;&hellip;是这样的。可怎么处理呢?</p>
    by Anders Liu(注册) on 2009/1/19 11:58:05
  • re:我的2008,征服天堂
    <p>博主是不是去了师部 做了侦查营长呢?</p>
    by huobazi(注册) on 2009/1/9 14:15:33
  • re:我的2008,征服天堂
    <p>@ghj1976:看来真的危机了</p>
    by 开心就好(注册) on 2009/1/9 10:17:37
  • re: 网络带宽的单位
    不过传输的时候,往往还有压缩。
    by luke(匿名) on 2008/12/15 11:00:21
  • re: 网络带宽的单位
    除10不仅仅是为了方便,在传输中,往往加上控制位,所以一个字节往往需要10Bit.
    by 关门放狗(匿名) on 2008/12/13 16:01:30
  • re: 多缓存并存
    对跨进程甚至跨服务器缓存的性能比较怀疑,进程通信和跨服务器通信代价不菲。即使有已有进程外数据可用,如果考虑在进程做份缓存,定期再进程间同步是否更佳?
    by jinglecat(匿名) on 2008/12/12 18:00:05
  • re: 网络带宽的单位
    好像还有一个为了方便换算,厂家使用的是 除10的处理方式的说法:于是100Mb/sec = 100M / 10 = 10M Byte/sec 所以我通常都是用除10而不是除8来做运算的。
    by kentliu(匿名) on 2008/12/11 11:38:55
  • re: 网络带宽的单位
    又不是大S小s
    by luke(匿名) on 2008/12/10 12:04:50

广告

 

我们通过一个实例来看 有And 操作符时候的最常见的一种情况。我们有下面一个表,

CREATE TABLE [dbo].[member](
[member_no] [dbo].[numeric_id] IDENTITY(1,1) NOT NULL,
[lastname] [dbo].[shortstring] NOT NULL,
[firstname] [dbo].[shortstring] NOT NULL,
[middleinitial] [dbo].[letter] NULL,
[street] [dbo].[shortstring] NOT NULL,
[city] [dbo].[shortstring] NOT NULL,
[state_prov] [dbo].[statecode] NOT NULL,
[country] [dbo].[countrycode] NOT NULL,
[mail_code] [dbo].[mailcode] NOT NULL,
[phone_no] [dbo].[phonenumber] NULL,
[photograph] [image] NULL,
[issue_dt] [datetime] NOT NULL DEFAULT (getdate()),
[expr_dt] [datetime] NOT NULL DEFAULT (dateadd(year,1,getdate())),
[region_no] [dbo].[numeric_id] NOT NULL,
[corp_no] [dbo].[numeric_id] NULL,
[prev_balance] [money] NULL DEFAULT (0),
[curr_balance] [money] NULL DEFAULT (0),
[member_code] [dbo].[status_code] NOT NULL DEFAULT (' ')
)

这个表具备下面的四个索引:

索引名 细节 索引的列
member_corporation_link nonclustered located on PRIMARY corp_no
member_ident clustered, unique, primary key located on PRIMARY member_no
member_region_link nonclustered located on PRIMARY region_no
MemberFirstName nonclustered located on PRIMARY firstname

当我们执行下面的SQL查询时候,

SELECT m.Member_No, m.FirstName, m.Region_No
FROM dbo.Member AS m
WHERE m.FirstName LIKE 'K%'
AND m.Region_No > 6
AND m.Member_No < 5000
go

SQL Server 会根据索引方式,优化成下面方式来执行。

select a.Member_No,a.FirstName,b.Region_No
from
(select m.Member_No, m.FirstName from dbo.Member AS m
where m.FirstName LIKE 'K%' and m.Member_No < 5000) a ,
-- 这个查询可以直接使用 MemberFirstName 非聚集索引,而且这个非聚集索引覆盖了所有查询列
-- 实际执行时,只需要 逻辑读取 3 次

(SELECT m.Member_No, m.Region_No from dbo.Member AS m
where m.Region_No > 6) b

-- 这个查询可以直接使用 member_region_link 非聚集索引,而且这个非聚集索引覆盖了所有查询列
-- 实际执行时,只需要 逻辑读取 10 次

where a.Member_No = b.Member_No
不信,你可以看这两个SQL 的执行计划,以及逻辑读信息,都是一样的。

其实上面的SQL,如果优化成下面的方式,实际的逻辑读消耗也是一样的。为何SQL Server 不会优化成下面的方式。是因为 and 操作符优化的另外一个原则。

1/26 的数据和 1/6 的数据找交集的速度要比  1/52 的数据和 1/3 的数据找交集速度要慢。


select a.Member_No,a.FirstName,b.Region_No
from
(select m.Member_No, m.FirstName from dbo.Member AS m
where m.FirstName LIKE 'K%'
-- 1/26 数据
) a,

(SELECT m.Member_No, m.Region_No from dbo.Member AS m
where m.Region_No > 6 and m.Member_No < 5000
-- 1/3 * 1/ 2 数据
) b
where a.Member_No = b.Member_No

当然,我们要学习SQL 如何优化的话,就会用到查询语句中的一个功能,指定查询使用哪个索引来进行。

比如下面的查询语句

SELECT m.Member_No, m.FirstName, m.Region_No
FROM dbo.Member AS m WITH (INDEX (0))
WHERE m.FirstName LIKE 'K%'
AND m.Region_No > 6
AND m.Member_No < 5000
go

SELECT m.Member_No, m.FirstName, m.Region_No
FROM dbo.Member AS m WITH (INDEX (1))
WHERE m.FirstName LIKE 'K%'
AND m.Region_No > 6
AND m.Member_No < 5000
go
SELECT m.Member_No, m.FirstName, m.Region_No
FROM dbo.Member AS m WITH (INDEX (MemberCovering3))
WHERE m.FirstName LIKE 'K%'
AND m.Region_No > 6
AND m.Member_No < 5000
go
SELECT m.Member_No, m.FirstName, m.Region_No
FROM dbo.Member AS m WITH (INDEX (MemberFirstName, member_region_link))
WHERE m.FirstName LIKE 'K%'
AND m.Region_No > 6
AND m.Member_No < 5000
go

这里 Index 计算符可以是 0 ,1, 指定的一个或者多个索引名字。对于 0 ,1 的意义如下:

如果存在聚集索引,则 INDEX(0) 强制执行聚集索引扫描,INDEX(1) 强制执行聚集索引扫描或查找(使用性能最高的一种)。
如果不存在聚集索引,则 INDEX(0) 强制执行表扫描,INDEX(1) 被解释为错误。

总结知识点:

  • 简单来说,我们可以这么理解:SQL Server 对于每一条查询语句。会根据实际索引情况(sysindexes 系统表中存储这些信息),分析每种组合可能的成本。然后选择它认为成本最小的一种。作为它实际执行的计划。
  • 成本代价计算的一个主要组成部分是逻辑I/O的数量,特别是对于单表的查询。
  • AND 操作要满足所有条件,这样,经常会要求对几个数据集作交集。数据集越小,数据集的交集计算越节省成本。

 

参考资料

本文演示代码下载地址:
http://www.sqlskills.com/pastConferences.asp

打印 | 张贴于 2008-01-18 10:11:00 | Tag:数据库开发管理心得

留言反馈

#回复: SQL Server 索引基础知识(7)----Indexing for AND 编辑
非常不错呀,有点意思……...
2008-01-22 21:51:00 | [匿名用户:x61q]
#回复: SQL Server 索引基础知识(7)----Indexing for AND 编辑
生成查询计划的理解那部分不是太明白。。。
2008-01-18 17:12:00 | [匿名用户:zzuyongp]
#SQL Server 索引基础知识(7)----Indexing for OR 编辑
我们仍然是通过例子来理解OR运算符的特征 我们仍然使用 http://blog.joycode.com/ghj/archive/2008/01/18/113870.aspx 中的 member 表,这时候,这个表的索引如下: 名字 描述 列 member_corporation_link nonclustered located on PRIMARY corp_no member_ident clustered, unique, primary key located on PRIMARY member_no...
2008-01-18 14:33:00 | [匿名用户:ghj1976]
#回复: SQL Server 索引基础知识(7)----Indexing for AND 编辑
基本正确,除了对生成查询计划的理解那部分。
2008-01-18 12:53:00 | [匿名用户:怡红公子]
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode.MVC引擎 0.5.1.8