第5周 堆表

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 原文:第5周 堆表欢迎来到SQL Server性能调优培训的第2个月。这个月将会是最有趣和最有挑战性的一个月,这个月我们专一只谈SQL Server中的索引,索引,还是索引。相信我,值得一个月去学习索引。
原文: 第5周 堆表

欢迎来到SQL Server性能调优培训的第2个月。这个月将会是最有趣和最有挑战性的一个月,这个月我们专一只谈SQL Server中的索引,索引,还是索引。相信我,值得一个月去学习索引。

今天我会谈下堆表(Heap Tables),在接下来的3周,我们会探讨下聚集索引,非聚集索引,还有SQL Server的索引战略。先来看下堆表。堆表就是没有聚集索引的表。如果SQL Server中的表能有一个聚集索引,那这个表被称为聚集表(Clustered Table),没有聚集索引(/非聚集索引)的表,我们称它为堆表。

在堆表里,数据没有任何方式的排序,它就是一个无序堆,无结构关联的记录。当你使用SELECT语句访问堆表时,SQL Server在执行计划里会使用表扫描(Table Scan)运算符,因为你没有定义合适的聚集索引。(堆表)没有表查找(Table Seek)这个运算符。这点非常重要。

下周你会学到,当我们提到聚集索引时,你是通过聚集索引扫描(Clustered Index Scan)、聚集索引查找(Clustered Index Seek)运算符来访问聚集索引的。在堆表你只有一个表扫描(Table Scan)运算符。表扫描意味着你必须扫描整张表,不以你表拥有的数据量来衡量。你的数据量越多,操作花费(时间)越长。

表扫描始终是个线性O(n)操作(更多关于大O介绍),它不以你越来越大的表来衡量。现在让我们一起详细看下在SQL Server中堆表的优点和缺点。

优点

堆表插入数据非常,非常,非常快。如我们刚才说的堆表就是一个数据堆。当你从传统电话本(拆开装订)把每页扯出来并把各页放在你面前的桌上时,你就拥有了一个堆表。在堆表的电话本里插入一个新的电话记录非常快:你分配一个8kb 的新页,在那页写上新的纪录,最后把那页与面前的其他页放一起,搞定。不需要保证任何的排序。

在SQL Server里是一样的:分配一个新页,在新页存新的纪录,把这页分配给堆表,搞定。这是一个非常快的方法,因为SQL Server不需要保证任何的排序。把新纪录存放在哪里完全由SQL Server自己决定。

因此在数据库架构里,这样的表设计有些时候是非常好的主意:这些表只有海量(huge)并行(parallel)的INSERT活动。考虑下你的登陆/审计表。当我绝不推荐在任何地方使用堆表。这里只是一些特定有意义的使用案例。但不是任何地方。

缺点

堆表除了插入数据非常快的优点外,也有很多缺点,当你决定创建堆表时若不考虑这些就不合适了。

第一个缺点,堆表在你访问表数据时会在存储子系统引发随机存取(random I/O) 。想象下对你的堆表执行简单的SELECT语句。如果数据没有缓冲在缓冲池,SQL Server会发起从你的存储系统进行物理读操作。这些读操作会是随机存取(random I/O),因为堆表的页是存在数据文件里某些地方的,它们并不相邻。

如果你使用传统的旋转存储(现在大多数情况还是这样的机械硬盘),在你的存储级别就有性能上的问题,因为随机存取是非常,非常慢的。SSD硬盘在这方面是大的游戏规则改变者,因为如果你在SSD硬盘执行随机存取(random I/O) 循序存取(sqquential I/O) ,这些都不是问题。因为两种操作不管哪样速度基本都是一样(随机存取(random I/O) 循序存取(sqquential I/O) 稍微慢一点)。

另外一个是明确只有在堆表里才有的被称为转发记录(Forwarding Records) 的问题。存在堆表里的记录在某些情况下(更新变长记录会移动记录的存储)可以从一页移动到另一页。如果这个发生的话,SQL Server会在原页存放一条指向记录存放新位置的转发记录(Forwarding Record) 。

当你访问你的数据的时候,SQL Server还是访问原页,并通过转发记录拿到在额外页你需要的记录。这会让你的读性能大幅度下降。如果你想了解更多转发记录(Forwarding Record)细节,并且如何避免它们,我建议你看下我的关于那个话题的第10个SQL Server Quickie。

小结

堆表在一些情况有它们的用处。一般我都建议创建聚集表(在上面定义一个聚集索引),但想下在一些特殊案例下,堆表可能是一个服务你业务需要更好方式(利用它的性能特性)。如果你想了解更多关于什么时候使用堆表更合适的细节,我也推荐Tomas Kejser's的博客帖子 聚集索引与堆表的对抗。Tomas会给你非常有争议却仍有用的洞察,(那就是)对你来说关于什么时候使用堆表是有意义的。

下周我会探讨更多关于SQL Server中的聚集索引。你会学到如何选择你的正确聚集主键,什么时候它们是好的,还有什么时候是坏的。请继续关注,下周见。

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
2月前
获得月份天数
获得月份天数
52 4
根据日期获得当天是星期几?
根据日期获得当天是星期几?
87 0
|
安全 Java Unix
第七周:函数
C语言会是你敲开编程大门的第一个语言吗?
108 0
|
缓存 资源调度 算法
技术周报 | 2021年第10周
技术周报 | 2021年第10周
153 0
1185. 一周中的第几天 : 简单日期统计模拟题
1185. 一周中的第几天 : 简单日期统计模拟题
|
C++ Windows
C++程序设计-第18周"务虚性"总结
回到课程主页,链接:C++程序设计课程主页-2012级   本周回顾了整个学其布置的任务,决定在考试即将到来之际,将做什么的问题交给同学们自己决定。
1159 1
|
C#
C#根据当前时间获取周,月,季度,年度等时间段的起止时间
原文:C#根据当前时间获取周,月,季度,年度等时间段的起止时间 最近有个统计分布的需求,需要按统计本周,上周,本月,上月,本季度,上季度,本年度,上年度等时间统计分布趋势,所以这里就涉及到计算周,月,季度,年度等的起止时间了,下面总结一下C#中关于根据当前时间获取周,月,季度,年度等时间段的起止时间的方法,废话不多说,直接贴代码,如果你觉得有用,请多多推荐。
1416 0
|
算法 C# 索引
C# 根据年、月、周、星期获得日期等
原文:C# 根据年、月、周、星期获得日期等 [参考] http://blog.csdn.net/livening/article/details/6049341 http://zhidao.baidu.com/question/378600365.html http://www.cnblogs.com/roy117/archive/2008/03/25/1121584.html   楼上几层的代码都太多了,不用那么复杂。
1579 0
|
C++
2014秋C++ 第5周项目 初识C++
课程主页在http://blog.csdn.net/sxhelijian/article/details/39152703,课程资源在云学堂“贺老师课堂”同步展示,使用的帐号请到课程主页中查看。 【项目1-见识初学者常见错误】下面是最经典和最简单的C++程序。在ideone.com中运行程序,并在能正确运行的程序基础上,“捣乱”制造些错误,对此进行观察。经验是从错误中得来的,这个项目就是要
1197 0