设为首页 收藏本站
查看: 707|回复: 0

[经验分享] 《Microsoft Sql server 2008 Internals》读书笔记--第六章Indexes:Internals and Management(5

[复制链接]

尚未签到

发表于 2015-6-28 19:41:34 | 显示全部楼层 |阅读模式
  
  《Microsoft Sql server 2008 Internals》读书笔记订阅地址:
  http://www.iyunv.com/downmoon/category/230397.html/rss      
  《Microsoft Sql server 2008 Internals》索引目录:
  《Microsoft Sql server 2008 Internal》读书笔记--目录索引
  
  
  前文简要介绍了堆中的非聚集索引行(Nonclustered index rows on a Heap)和聚集表中的非聚集索引行(Nonclustered index rows on a Clustered table)
  今天我们继续学习三类特殊的非聚集索引行:
  1、非惟一的非聚集索引行(nonunique Nonclustered index rows)
  2、使用包含性列的非聚集索引行(nonunique Nonclustered index rows with included Columns(using include))
  3、使用筛选器的非聚集索引行(Nonclustered index rows with Filters(Filtered Indexes))
  ■ 非惟一的非聚集索引行(nonunique Nonclustered index rows)
  我们已经知道一个非聚集索引的叶级必须有一个书签,以便于从叶级定位到实际的数据行,而(非聚集索引的)非叶级只需要帮助我们穿越到低级别的叶的pages。一个惟一的非聚集索引(如前例中的主键和惟一的非聚集索引),非叶级行仅仅包含非聚集索引键值和子页指针(Child-Page pointer),然而,如果索引是不惟一的,则非级行包含非聚集索引键值和子页指针和书签值。换句话说,在一个不惟一的、非聚集的索引中,书签值被加到一个非聚集索引键,以确保惟一性(作为书签,在定义时,必须是惟一的)。
  记住创建一个索引行的意图:SQL Server并不关心不惟一的索引键是否包含重复值。如果一个索引没有被定义成惟一的,即便所有的非叶级索引行都是惟一的,非叶级索引行总是包含书签。我们可以通过以下三个例子来回顾叶级和非叶级行大小:


CREATE NONCLUSTERED INDEX TestTreeStructure
ON Employee (SSN);
go
CREATE UNIQUE NONCLUSTERED INDEX TestTreeStructureUnique1
ON Employee (SSN);
go
CREATE UNIQUE NONCLUSTERED INDEX TestTreeStructureUnique2
ON Employee (SSN, EmployeeID);
go
SELECT si.[name] AS iname
    , index_depth AS D
    , index_level AS L
    , record_count AS 'Count'
    , page_count AS PgCnt
    , avg_page_space_used_in_percent AS 'PgPercentFull'
    , min_record_size_in_bytes AS 'MinLen'
    , max_record_size_in_bytes AS 'MaxLen'
    , avg_record_size_in_bytes AS 'AvgLen'
FROM sys.dm_db_index_physical_stats
    (DB_ID ('IndexInternals')
    , OBJECT_ID ('IndexInternals.dbo.Employee')
    , NULL
    , NULL
    , 'DETAILED') AS ps
    INNER JOIN sys.indexes AS si
        ON ps.[object_id] = si.[object_id]
            AND ps.[index_id] = si.[index_id]
WHERE ps.[index_id] > 2;
go  
http://public.blu.livefilestore.com/y1pyZpUL7n_95jLg-S2RG1LRf5Q8GZbzAJtfVpmXyxiM3BOPXsZw2Qixga-AOtxGpxHiAbRc7grr2w5tdOZnhwFbQ/pageIndex20100_15.png
注意上图中,索引的叶级(Level 0)都是一样的。第一个索引和第三个索引是相同的。对于第一个索引的EmployeeID被加,是因为它是聚集键(因此作为书签)。第三个索引中EmployeeID已经在索引中,没有被重复添加。然而,在第一个索引中,由于它未被定义成unique,SQL Server不得不添加主键到所有树经过的行。在第二个索引中,因为SSN是惟一的、单独的,因此SQL Server在所有树到之行添加EmployeeID,有兴趣的朋友可以用DBCC IND和DBCC PAGE进一步分析其物理行结构。
  ■使用包含性列的非聚集索引行(nonunique Nonclustered index rows with included Columns(using include))
  到目前为止,对于所有的非聚集索引,我们重点放在索引被约束创建时的物理方面或创建测试物理结构的索引。无论如何,我们必须遵守不能超过900字节或16个列的限制,因为这些限制的存在有助于我们确保索引的可扩展性,但同时它保守地限定了能被用于索引的列最大数。MSDN也有介绍:可以将非键列包含在非聚集索引中,以避免超过当前索引大小的限制(最大键列数为 16,最大索引键大小为 900 字节)。数据库引擎计算索引键列数或索引键大小时,不考虑非键列。请看:

  http://msdn.microsoft.com/zh-cn/library/ms190806%28SQL.90%29.aspx
  我们也可以查看MSDN:非聚集索引设计指南
  http://msdn.microsoft.com/zh-cn/library/ms179325.aspx
  在某些情况下,我们需要在一个索引中添加的列允许SQL Server(当访问一个范围查询(range query)时)消除书签查询 ,这就是所谓的覆盖索引(Covering Indexes),这里有关于覆盖索引的介绍:http://en.wikipedia.org/wiki/Index_%28database%29#Covering_Index
  一个覆盖索引是一个匹配对应查询的所有信息能够被在叶级查找到的非聚集索引,因此SQL Server根本不需要访问数据页,这在优化复杂的查询时是一个强大的工具,只需要在创建索引时加上include子句即可。参看MSDN:http://msdn.microsoft.com/zh-cn/library/ms188783%28SQL.90%29.aspx
  INCLUDE ( column_name [ ,...n ] ) ]。 所有被关键字Include列出的列,允许你在一个非聚集索引的叶级超过900字节或16列的限制,这些包含性列仅仅出现在叶级,对索引行的排序没有任何影响。在某些特定情况下,SQL Server会自动加一个包含性列到你的索引中,(在一个分区给中创建索引而没有使用ON Group或partition_schema_name未被定义时触发)。
  ■使用筛选器的非聚集索引行(Nonclustered index rows with Filters(Filtered Indexes))  
  筛选索引是一个非聚集索引的优化形式
    http://technet.microsoft.com/en-us/library/cc280372.aspx

  如果不使用筛选器,非聚集索引的叶级为表中的每行数据包含一个索引行,逻辑排序由索引所定义。SQL Server 2008中,你可以在创建索引时添加一个筛选谓词,这允许SQL Server仅仅为谓词匹配的行创建非聚集索引行,从而限制了非聚集索引的大小。这在以下情况下非常有用:
  1、当一个列包含大多数为Null而查询仅仅需要数据为Not Null。与稀疏列(SPARSE columns)结合时尤其有用。
  2、当一个列包含限定数量的感兴趣值或者你想仅仅强化一组值的惟一性。比如,你想允许Employee表的SSN列为Nul值。使用限制,SQL Server允许仅仅单个行为Null,然而,使用筛选索引,你可以创建一个惟一索引在所有SSN为not Null的行。这个语法应该类似:


Create UNIQUE NoCLUSTERED INDEX SSN_NOT_NULLs
On Employee(SSN)
WHERE SSN IS NOT NULL   3、当查询检索仅仅在一个特定的范围(range of data),并且你想在这些数据增加索引在,而不是在全表。例如,你有一个表,按月分区,包含了三年地数据(2008,2007,2006)。一个小组想重点分析2007年的第四季度。此时并不需要对所有数据创建一个宽的非聚集索引,只须在创建索引时(也适用于include)关注


WHERE SalesDate>'20071001' and SalesDate

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-81331-1-1.html 上篇帖子: SQL Server如何清除连接过的服务器名称历史? 下篇帖子: SQL Server 2008中SQL增强之三:Merge(在一条语句中使用Insert,Update,Delete)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表