深入解析SQL Server 2008

深入解析SQL Server 2008 笔记
        </h1>
        <div class="clear"></div>
        <div class="postBody">

深入解析SQL Server 2008 笔记

目录

F

F

F

F

F

F

F

第一章 sqlserver2008架构和配置

版本

SELECT SERVERPROPERTY('Edition')
--Developer Edition (64-bit)

SELECT SERVERPROPERTY(‘EngineEdition’)
–3

 

EngineEdition返回:2、3、4
可能是企业版,评估版,开发版
2 标准版 工作组版
3 开发版
4 express版 Windows embedded SQL

F

sql元数据

SELECT [name]
FROM sys.[objects]
WHERE [type_desc]='system_table'

 

兼容性视图,兼容sql2000

sql2005和sql2008的新功能不包含在兼容性视图里,例如表分区和资源调控器
兼容性视图只是为了向前兼容,在将来版本sqlserver将会删除所有兼容性视图

F

使用sql2008查询sysprocess中所有可用信息时,你必须访问3个DMV:
SYS.[dm_exec_connections]
SYS.[dm_exec_requests]
SYS.[dm_exec_sessions]
因为增加了MARS,所以sql2000的sysprocess不能标识出单个连接了

 

目录视图显示的列完全不同于兼容视图中的列

--目录视图
SELECT * FROM sys.[databases]
--兼容视图
SELECT * FROM sys.[sysdatabases]

 

F

 

查看视图定义

SELECT OBJECT_DEFINITION(OBJECT_ID('sys.[tables]'))
SELECT * FROM sys.[system_sql_modules] WHERE [object_id]=OBJECT_ID('sys.[tables]')

 

sys.objects包含各种对象类型通用的所有属性列,sys.tables和sys.views包含有与sys.objects完全相同的列

F

信息架构视图

系统函数

sql7.0引入了系统函数,在sql2000中增强了这些函数

属性函数

 

F

如果只查看sue是否拥有某一个数据库访问权限,则无法使用系统提供的存储过程,使用目录视图这些查询将非常简单

SELECT [name]
FROM sys.[databases]
WHERE SUSER_NAME([owner_sid])='sue'

 

 

sql2008元数据层跟sql2005几乎一样

F

sqlserver数据库引擎主要组件

关系引擎(也称为查询处理器),存储引擎,SQLOS

DMV也可以管理数据仓库(sql2008的新功能)的性能报告提供更多有效数据

F

dm_exec_:执行有关的


dm_os_:系统信息

dm_tran_:事务细节信息


dm_io_:网络和磁盘I/O活动 ,SELECT * FROM sys.[dm_io_virtual_file_stats]()函数返回数据和日志文件的I/O统计信息

dm_db_:数据库和数据库对象细节信息:SELECT * FROM sys.dm_db_index_physical_stats()

 

 

使用MDAC2.8或更早版本的客户端无法使用共享内存协议

F

sql2008还允许你创建TDS端点,以便sqlserver侦听附加的TCP端口,例如镜像 

查询优化和查询执行

关系引擎(优化器)和存储引擎的通信 使用OLEDB行集(row set)实现,行集是OLEDB结果集术语,存储引擎包含需要真正访问和修改磁盘数据的组件

查询优化器
无法优化的语句:例如控制流和DDL命令将被编译为内部形式,可优化的语句将被做上标记,然后传递到查询优化器

 

 

查询树

规范化树

 

F

查询优化器使用修剪启发式算法

对于after触发器:触发器计划(生成触发器执行计划)在修改语句激活触发器之后和提交修改之前执行

 

触发器的特定步骤没有编译到执行计划中

查询执行器的详细介绍:http://sqlserverinternals.com/companion/

存储引擎主要包括3部分:访问方法,锁,事务服务,实用工具命令

 

访问方法实际不检索页面,他向缓存管理器发送请求,最后缓存管理器在其缓存中提供页面,

或者从磁盘读取页面到缓存,look-ahead预测行机制对页面上的行货索引条目进行鉴定

F

 

所有用户数据都存储在数据页或LOB页上

事务4个属性:原子性,一致性,隔离性,持久性

F

事务服务
事务管理组件

F

其他操作:存储引擎还包含用于控制实用工具的组件:例如大容量加载,dbcc命令,全文索引填充和管理,备份和还原

 

SQLOS

SQLOS的两个主要函数是计划和内存管理,同步化,内存broker,sqlserver异常处理,死锁检测,扩展事件,异步I/O

扩展事件:sql2008的资源调控器使用扩展事件管理资源使用率

numa架构

F

numa节点中的CPU数目取决于硬件生产商

内存节点是基于硬件numa而创建的,因此不受软件numa的影响

将scheduler翻译成计划程序,一头雾水

SQL2005之前的scheduler称为用户架构scheduler(UMS) user  Management scheduler
SQL2005和2008称scheduler为SOSscheduler,并进一步改进了UMS  system optimization  scheduler

多任务等待 等待类型
SOS_SCHEDU-LER_YIELD 223

http://www.golden-book.com/booksinfo/17/1754478.html

F

当更改关联掩码时,导致scheduler从online向offline切换时,已经分配给该scheduler的任何工作必须先完成,并且系统不再向该scheduler分配新工作

sqlserver工作线程 workers

SQLSERVER使用自己的计划程序sql agent而放弃Windows的计划程序scheduler,这样做可以获取更高的控制权和可伸缩性

F

spid优先分配给负载最低的scheduler

SELECT [load_factor] FROM sys.[dm_os_schedulers]

线程和纤程

每个numa节点都有自己的惰性写入器和IOCP io完成端口 iocp是一种网络侦听器

 

sql mail和sql xml需要线程模型

http://support2.microsoft.com/ph/2855

numa和scheduler

单个处理或SMP机器被看成是单个numa
scheduler和含有numa的cpu之间不存在硬映射

F

当非闲置线程没有让出scheduler,scheduler监视器将产生错误(17883),当应用程序(不是sqlserver)独占CPU时,将出现17883错误

scheduler监视器还负责向scheduler发送消息,帮助他们平衡工作负荷

使用trace flag 跟踪标志8002启动sqlserver,通过使用跟踪标志,将cpu映射到某个实例上

将scheduler绑定到cpu

scheduler和CPU不是一对一的关系,负载不大时,Windows可以在一个cpu上运行两个scheduler

F

parent_node_id:scheduler所属节点id,也称为父节点,代表numa节点

sys.[dm_os_schedulers]视图解释

F

F

DAC

复制代码
SELECT *
FROM SYS.[tcp_endpoints] AS E JOIN SYS.[dm_exec_sessions] AS S
ON E.[endpoint_id]=S.[endpoint_id]
WHERE E.[name]='DEDICATED ADMIN CONNECTION'

name endpoint_id principal_id protocol protocol_desc type type_desc state state_desc is_admin_endpoint port is_dynamic_port ip_address
Dedicated Admin Connection 1 1 2 TCP 2 TSQL 0 STARTED 1 0 1 NULL
TSQL Default TCP 4 1 2 TCP 2 TSQL 0 STARTED 0 0 1 NULL
inven 65536 261 2 TCP 3 SERVICE_BROKER 0 STARTED 0 4030 0 NULL

复制代码

 

默认情况下,DAC只能本地使用,但DBA也可以配置DAC允许远程连接

sp_configure 'remote admin connections', 1;
GO
RECONFIGURE;
GO

 

只能用sysadmin服务器角色成员连接


DAC不能执行backup 和restore 操作

通过DAC分配的特殊线程,不能终止该线程(DAC线程不停监听),只能终止DAC会话,DAC scheduler具有最高优先级 255 ,DAC 没有惰性写入器,有自己的IOCP,workers和闲置线程

F

express只能使用7806跟踪标志来开启DAC

 

内存

为什么数据页面中只有 dbid,fileno,pageno,因为sqlserver使用 dbid,fileno,pageno三者标识符生成哈希函数生成哈希存储桶,哈希桶中的key,即使庞大内存,也能在几秒钟找到内存中的数据页面

哈希存储桶的数目由sqlserver设置,具体数目取决于缓冲池的总容量

sql6.5的时候是可以手动设置哈希存储桶的
EXEC sys.[sp_configure] @configname = 'advanced options', -- varchar(35)
@configvalue = 1 -- int
RECONFIGURE WITH OVERRIDE
--HASH buckets
--DBCC BUFCOUNT
--DBCC SQLPERF(HASHSTATS)

 

 

访问内存中的数据页

buffer pool里面的页面使用哈希存储方法

F

管理数据缓存中的页面

LRU-K算法

F

使操作系统的可用物理内存保持在5MB(偏移量在200kb左右)大小,以防止page out,如果操作系统可用内存小于5mb,惰性写入器将释放内存给操作系统

触发checkpoint
1、sql2008中,使用checkpoint命令可以同时运行多个checkpoint(在不同的数据库)

2、为了自动激活checkpoint,必须完成的最少工作量一般是每分钟10MB日志

F

sqlserver扩展事件sqlserver.checkpoint_begin和sqlserver.checkpoint_end来监视checkpoint的活动情况

checkpoint进程通过缓冲池时按无序方式扫描页面,把脏页 使用单个写入的方式,类似mysql的double write,gather-write

在配置管理器里,指定sqlserver服务的启动参数 使用-k 参数 ,其后再跟上小数,指定的值表示checkpoint进程每秒可以写入的兆字节数

这样可以控制checkpoint的IO,但是当参数值很低的时候,将导致较长的恢复时间
在产品环境上使用 -k参数之前,应该确保有足够的硬件来支持sqlserver提交的IO请求

时钟算法

除了数据缓存之外,sql2008使用共同的缓存框架 cache store
包括:缓存存储,用户存储(该存储类型实际和用户无关),对象存储

缓存存储:执行计划
用户存储:元数据
对象存储:SNI 网络缓冲区

F

memory broker

复制代码
SELECT *
FROM sys.[dm_os_ring_buffers]
WHERE [ring_buffer_type]='ring_buffer_memory_broker'

<Record id = “652” type =“RING_BUFFER_MEMORY_BROKER” time =“27376318”><MemoryBroker><DeltaTime>817</DeltaTime><Pool>1</Pool><Broker>MEMORYBROKER_FOR_RESERVE</Broker><Notification>GROW</Notification><MemoryRatio>100</MemoryRatio><NewTarget>10506</NewTarget><Overall>11093</Overall><Rate>0</Rate><CurrentlyPredicted>0</CurrentlyPredicted><CurrentlyAllocated>0</CurrentlyAllocated><PreviouslyAllocated>0</PreviouslyAllocated></MemoryBroker></Record>

复制代码

 

F

32位操作系统没有使用AWE的话,不推荐启用 “锁定内存页”,虽然sqlserver在未启用AWE时将忽略“锁定内存页”,否则系统上的其他进程可能会受影响

F

target memory

SELECT * FROM sys.[dm_os_sys_info]

 

F

SELECT DISTINCT [type] FROM sys.[dm_os_memory_clerks]

 

F

[buckets_avg_scan_hit_length] 在找到搜索项之前,存储桶中已检查条目的平均数
非常大的数可能说明小于最佳缓存 ,可以考虑运行DBCC FREESYSTEMCACHE('all')来删除缓存存储中的未用条目.

 


--object plans:指定要释放对象计划(存储过程,触发器,用户定义函数的执行计划)
DBCC FREESYSTEMCACHE('object plans')


--sql plans:指定要释放即席(ad-hoc)语句的计划,包括预编译的语句
DBCC FREESYSTEMCACHE('sql plans')


--bound trees:指定要释放视图,约束,默认的计划
DBCC FREESYSTEMCACHE('bound trees')

--力伟的文章 清空引用tempdb的session http://www.cnblogs.com/stswordman/p/3358496.html
--DBCC FREESYSTEMCACHE('ALL')指定all即清空object plans、sql plans、bound trees

 

clock_hand 时钟指针类型 外部指针 内部指针 ,记住,每个存储都有两个时钟指针类型

非本地内存和外来内存不一样
numa节点使用其他节点的内存,称为外来内存,外来内存被看成是本地内存
非本地内存 跨节点访问内存

 

没有硬件numa的计算机上使用软件numa的优势是减少IO和惰性写入器瓶颈
在含有8个cpu而无硬件numa的计算机上,只拥有一个IO线程和一个惰性写入器线程,这就存在瓶颈,配置4个软件numa节点,提供4个io线程和4个惰性写入器线程,这样能提高性能

numa和内存

预读

1、堆上的表扫描
2、索引扫描
扫描才有预读

F

服务器资源调控器

F

ALTER RESOURCE GOVERNOR 

 

F


工作负荷组,会话,批处理,语句之间的关系

F

F

F

1、启用资源调控器

2、分类器函数 根据系统函数和属性函数来确定工作负荷组

3、工作负荷组

4、资源池

工作负荷组,会话,批处理,语句之间的关系

F

F

复制代码
USE [master]
GO
--创建一个工作时间的资源池
CREATE RESOURCE POOL pProductionProcessing
WITH(MAX_CPU_PERCENT=100,MIN_CPU_PERCENT=50);

–创建一个工作时间的工作负荷组
CREATE WORKLOAD GROUP gProductionProcessing
WITH(IMPORTANCE =MEDIUM)
;

–配置工作负荷组和工作资源池进行关联
ALTER WORKLOAD GROUP [gProductionProcessing]
USING [pProductionProcessing];
GO

ALTER RESOURCE GOVERNOR RECONFIGURE;
GO

–创建一个非工作时间的资源池
CREATE RESOURCE POOL pOffHoursProcessing
WITH(MAX_CPU_PERCENT=50,MIN_CPU_PERCENT=0);

–创建一个非工作时间的工作负荷组
CREATE WORKLOAD GROUP gOffHoursProcessing
WITH(IMPORTANCE =LOW);

–配置非工作负荷组和非工作资源池进行关联
ALTER WORKLOAD GROUP [gOffHoursProcessing]
USING [pOffHoursProcessing];
GO

–当改变了工作组或资源池,都需要重新配置资源调控器
ALTER RESOURCE GOVERNOR RECONFIGURE;
GO

USE [master]
GO
CREATE TABLE tblClassifierTimeTable(strGroupName sysname NOT NULL,
tStartTime TIME NOT NULL,
tEndTime TIME NOT NULL)
GO

–将时间值插入到表以使分类器函数能够利用时间值负载工作
INSERT INTO tblClassifierTimeTable VALUES(‘gProductionProcessing’,‘6:35 AM’,‘6:15 PM’);
GO

CREATE FUNCTION [dbo].fnTimeClassifier ( )
RETURNS sysname
WITH SCHEMABINDING –如果表名不加dbo,就不能绑定架构[dbo].tblClassifierTimeTable
AS
BEGIN
DECLARE @strGroup sysname
DECLARE @loginTime TIME
SET @loginTime = CONVERT(TIME, GETDATE())
SELECT TOP 1
@strGroup = strGroupName
FROM [dbo].tblClassifierTimeTable

    </span><span style="color: rgba(0, 0, 255, 1)">WHERE</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">tStartTime</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">&lt;=</span> <span style="color: rgba(0, 128, 0, 1)">@loginTime</span>
            <span style="color: rgba(128, 128, 128, 1)">AND</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">tEndTime</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">&gt;=</span> <span style="color: rgba(0, 128, 0, 1)">@loginTime</span>
    <span style="color: rgba(0, 0, 255, 1)">IF</span> ( <span style="color: rgba(0, 128, 0, 1)">@strGroup</span> <span style="color: rgba(0, 0, 255, 1)">IS</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span><span style="color: rgba(0, 0, 0, 1)"> )
        </span><span style="color: rgba(0, 0, 255, 1)">BEGIN</span>
            <span style="color: rgba(0, 0, 255, 1)">RETURN</span> <span style="color: rgba(0, 128, 0, 1)">@strGroup</span>
        <span style="color: rgba(0, 0, 255, 1)">END</span>

–如果为null,使用gOffHoursProcessing
RETURN ‘gOffHoursProcessing’
END
GO
–如果这里不加dbo ,就会报错消息 4512,级别 16,状态 3,过程 fnTimeClassifier,第 19 行
–无法将 函数’dbo.fnTimeClassifier’ 绑定到架构,因为名称 ‘tblClassifierTimeTable’ 对于架构绑定无效。名称必须由两部分构成,并且对象不能引用自身。

–重新配置资源调控器以使用新的分类函数
ALTER RESOURCE GOVERNOR WITH( CLASSIFIER_FUNCTION=dbo.fnTimeClassifier);
ALTER RESOURCE GOVERNOR RECONFIGURE
GO

ALTER RESOURCE GOVERNOR WITH( CLASSIFIER_FUNCTION=null);
ALTER RESOURCE GOVERNOR RECONFIGURE
GO

–该加dbo的都加dbo

复制代码

 sql2008可以控制内存和cpu,但无法控制IO

资源调控器控制

cpu控制是软限制

内存限制是硬限制

120/200=60%  总cpu资源的60% 双核cpu 

80/200=40%   总cpu资源的40%

随着越来越多的资源被分配到scheduler中,这种反常现象会逐渐消失,但是由于存在跨多个CPU管理scheduler资源的工作方式,因此缺少显式的控制方法

--关闭资源调控器
ALTER RESOURCE GOVERNOR DISABLE
ALTER RESOURCE GOVERNOR RECONFIGURE

使用跟踪标志8040来启动sqlserver实例,将禁用资源调控器,用-m -f参数也能达到同样效果

F

资源调控器DMV

F

SQL2008配置

一般在Windows安装过程中都已经安装了网络协议,网络协议属于sqlserver的安装组成部分,只有客户端和服务器上同时安装了相应的网络协议,sqlserver网络库才能工作

F

sql2000引入了对多个实例的支持,并开始使用名为SSRP SQLSERVER Resolution Protocol的新协议来侦听UDP端口1434

sql2005使用sql broswer代替了SSRP协议

F

系统页面文件的位置,如果可能把sys.pagefile放到不同的驱动器上,而不只是放在sqlserver使用的文件上

F

F

防火墙

服务器配置

F

有16个高级选项

--可以查看sql2008中68个服务器配置选项,2008r2有70个
SELECT * FROM sys.[configurations] 
SELECT * FROM sys.[configurations] WHERE [is_advanced]=1

 

F

--查看哪些选项是动态的,不需要重启sqlserver ,修改了配置之后看一下[value_in_use]是否跟配置值一样知道是否生效
SELECT * FROM sys.[configurations] WHERE [is_dynamic]=1

 

1532             set working set size                0  将废除

F

因为无法将AWE映射内存page out到sys.pagefile文件中,所以所有实例的最小服务器内存总和应该小于计算机的总物理内存

因为无论是否使用连接,每个连接的开销大约都为28KB

 

106              locks                               0  被废除

F

F

sqlserver将在日志达到总数的70%而且小于所估计的数量时执行checkpoint

开头的时候说:为了自动激活checkpoint,必须完成的最少工作量一般是每分钟10MB日志

备份压缩默认值,只有企业版才能压缩备份,但是任何版本都可以解压缩备份

备份压缩 (SQL Server)为备份文件分配空间
压缩量取决于
备份的数据类型:字符数据的压缩大于其他数据类型
数据是否加密:加密数据的压缩明显小于同等条件下未加密的数据

 

查看备份压缩比率

SELECT  [compressed_backup_size] / [backup_size]
FROM    [msdb]..[backupset]

 

F

压缩备份的算法和数据库压缩算法(页压缩,行压缩)差别很大,备份压缩使用类似于zip的压缩算法,他仅在数据中寻找架构

文件流访问级别
使用TSQL或Win32文件系统接口访问该数据,以提供对数据的流访问,文件流使用Windows系统的缓存来缓存文件数据

F

查询等待
set lock_timeout 

8645错误

 

1569 blocked process threshold (s) 5 
--最大设置可以为86400秒

 

F

--查看并行度 通过查询 sys.[dm_os_tasks]DMV观察sqlserver何时并行执行查询,在多个cpu上运行的查询为每个线程分配一行
SELECT  *
FROM    sys.[dm_os_tasks]
ORDER BY [session_id] ,
        [request_id]

 

默认跟踪 文件达到20MB时,将创建新文件并使用连续数字后缀作为文件名

为每个实例保存的跟踪文件数不超过5个

F

跟踪文件以128K块为单位写入trc文件

默认跟踪 跟踪的事件:数据库文件大小更改,错误和警告条件,全文爬网操作,对象create,alter,drop操作,权限,对象所有权更改,内存更改事件

不会大于128KB

16:21:02.2356884 sqlservr.exe 2528 WriteFile D:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\audittrace20140928091301_3.trc SUCCESS Offset: 96,091,648, Length: 70,144, I/O Flags: Non-cached, Write Through, Priority: Normal

 

16:20:52.9501045 sqlservr.exe 2528 WriteFile D:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\audittrace20140928091301_3.trc SUCCESS Offset: 96,075,264, Length: 4,096, I/O Flags: Non-cached, Write Through, Priority: Normal

 

F

 

F

第二章 更改跟踪、跟踪和扩展事件

触发器和事件通知

事件通知其实是特殊的DDL触发器,他们像service broker队列发送消息,而不是调用用户程序
事件通知和DDL触发器最大的不同在于,他不需要事务,因此他支持大量非事务事件

 

事件通知

SQL Server 事件通知(Event notifications)》听风吹雨

F

 

DDL触发器和元数据有关
DML触发器在DML编译过程中进行解析,解析后通过内部函数检查每一个相关表

 

更改跟踪

sql2008包含两个可用于支持同步化的相似技术:更改跟踪和变更数据捕获(不是关系引擎的功能,他使用外部日志读取器完成自己的工作)

和变更数据捕获相比(他记录每个行的完整修改历史)更改跟踪是轻量级的

F


在事务提交时,每个合格事务被分配一个唯一的称为提交序号(CSN)的升序标识符,然后CSN
和事务标识符transactionID,日志序列信息lsn,开始时间和其他数据一起被插入到提交表

F

1、开启数据库的更改跟踪

ALTER DATABASE [sss] 
SET CHANGE_TRACKING =ON

 

运行该语句目录数据库中的隐藏系统表将被填充,需要对事务发生进行资格鉴定


2、隐藏表也叫提交表,CSN提交序号
使用DAC连接查看提交表的表结构

SELECT *
FROM sys.[all_columns]
WHERE object_id=OBJECT_ID('sys.syscommittab')

 


有关表中行的修改信息存储在单独的系统表中,该系统表是在用户表上启用更改跟踪时创建的
查看提交表的数据

SELECT *
FROM sys.[dm_tran_commit_table]

 

3、内部清除任务每隔30分钟运行一次
默认值是CHANGE_RETENTION=2 DAYS

ALTER DATABASE [sss] 
SET CHANGE_TRACKING=ON(AUTO_CLEANUP=ON,CHANGE_RETENTION=1 DAYS)

SELECT * FROM sys.[change_tracking_databases] –目录视图查询每个数据库的当前清除和保留设置

 

4、表级别配置

注意:提交表是数据库级别的:跟踪数据库的所有事务
内部更改表是表级别的,跟踪用户表的更改

 


启动表的更改跟踪之后,在用户表里添加一个隐藏列,通过事务ID跟踪特定行的变化,另外,还可以启用名为“列跟踪”的可选功能

ALTER TABLE [dbo].[Arrays]
ENABLE CHANGE_TRACKING
--消息 4997,级别 16,状态 1,第 1 行
--无法对表 'a' 启用更改跟踪。更改跟踪要求该表的主键。请先创建该表的主键,然后启用更改跟踪。

 

INSERT [Arrays]([arrid],[array])
SELECT '1','2'

 

5、内部更改表

开启了内部更改表之后都不见有系统表

复制代码
ALTER DATABASE [sss] 
SET CHANGE_TRACKING =ON

SELECT *
FROM sys.[all_columns]
WHERE object_id=OBJECT_ID(‘sys.syscommittab’)

ALTER TABLE [dbo].[nums]
ENABLE CHANGE_TRACKING

复制代码

sys.[change_tracking_object id]

 


6、更改跟踪的隐藏列
为某个表开启了更改跟踪之后,除了创建内部表之外,还将向该表添加一个隐藏的8字节列用于记录每行最后修改的事务id,在更新更改跟踪后,你会发现表的数据大小相应地增加了,如果某个表禁用了更改跟踪,该列将和内部表一起被删除

 

使用DAC可以看到那个隐藏列,但是要显式指定列名

 

F

复制代码
ALTER DATABASE [sss] 
SET CHANGE_TRACKING =ON

SELECT *
FROM sys.[all_columns]
WHERE object_id=OBJECT_ID(‘sys.syscommittab’)

ALTER TABLE [dbo].[nums]
ENABLE CHANGE_TRACKING

SELECT *
FROM sys.[all_objects]
WHERE [name] LIKE ‘%change_tracking%’
–change_tracking_1954106002

–使用DAC也没有办法查询
SELECT * FROM sys.change_tracking_1954106002

复制代码
消息 208,级别 16,状态 1,第 1 行
对象名 'sys.change_tracking_1954106002' 无效。

固定开销包括18字节的事务id,CSN和操作类型,以及来自目标表的主键大小

F

--使用DAC也没有办法查询
SELECT * FROM sys.change_tracking_1954106002

INSERT INTO [dbo].[nums]
SELECT 1

从执行计划看到更改跟踪还会插入到内部更改表

 

删除的时候也会修改更改跟踪表

DELETE FROM [nums]

更改跟踪表更新 会插入旧值和新值到内部更改表

UPDATE [nums] SET [n]=2 

DECLARE @context VARBINARY(128)=CONVERT(VARBINARY(128) ,SUSER_NAME());

WITH change_tracking_context(@context)
UPDATE

不仅内部更改表的插入操作在事务结束时同步发生,提交表的插入操作也在提交时发生,插入的行包含在内部表和目标表的隐藏列中使用的相同事务id,此时,还将为该事务分配一个CSN,因此可以将CSN看成是版本号,该版本号应用于事务修改的所有行

F

列跟踪

--打开TRACK_COLUMNS_UPDATED启用列跟踪
ALTER TABLE  [dbo].[nums]
ENABLE CHANGE_TRACKING
WITH (TRACK_COLUMNS_UPDATED =ON)

 

F

changetable函数是系统表值函数

SELECT E.* ,
[C].SYS_CHANGE_VERSION 
FROM [dbo].[nums] E
CROSS APPLY CHANGETABLE(VERSION [sss].[dbo].[nums],( n),( [n])) C

 


在version模式下,访问每行并获取每列以及隐藏列的值(修改该行的上一个事务id),
使用该事务id作为联接到提交表的键,以选区相关的CSN并填充到sys_change_version列,

为了填充sys_change_context列,也可以使用该事务id和主键来联接内部跟踪表

复制代码
DECLARE @last_version BIGINT =8;

SELECT *
FROM CHANGETABLE(
CHANGES [dbo].[nums],@last_version) C;

–change模式中传给CHANGETABLE()函数,并获取表中行的后续版本

复制代码
复制代码
DECLARE @last_version BIGINT =8;

SELECT
[C].sys_change_version,
[C].sys_change_operation,
[C].sys_change_context,
E.*
FROM CHANGETABLE(
CHANGES [dbo].[nums],@last_version) C
LEFT OUTER JOIN
[dbo].[nums] E
ON E.[n]=[C].N;

复制代码

跟踪 sql trace

F

跟踪提供了180个事件,sqlserver profiler

sql跟踪是一种sqlserver数据库引擎技术,客户端profiler工具其实是服务器端功能的包装器

特定代码已经拦截到其执行路径中,当触发执行路径时,将激活不同的事件

他是一个共享资源,管理任何使用者创建的所有跟踪,数据库引擎中存在各种事件创建器,例如查询处理器,锁管理器,缓存管理器

 

跟踪I/O提供程序

内部跟踪组件:跟踪控制器

F

为了避免线程等待跟踪缓冲区,请务必使用足够快的磁盘系统执行跟踪,为了监视这些等待,可以观察SQLTRACE_LOCK和IO_COMPLETION等待类型

 

通过在sqlserver中监视TRACEWRITE等待类型,也可以发现自己是否可能收到sql profiler的错误信息,随着线程等待缓冲区释放空间,收到错误信息的可能性将逐渐增加

只要服务器上至少存在一个活动的跟踪,就会启动后台跟踪管理线程,该后台管理线程负责刷新文件提供程序的缓冲区(每4分钟一次),另外还负责关闭基于行集的过期跟踪(如果跟踪删除事件已经超过了10分钟,将出现过期跟踪),通过不定期刷新文件提供程序缓冲区,而不是每次收集一个事件就刷盘,sql可以利用大数据块写入操作降低跟踪开销,特别在活动性极高的服务器上

 

复制代码
--查看跟踪缓存区的等待
SELECT *
FROM sys.[dm_os_wait_stats]
WHERE [wait_type] LIKE '%trace%'
AND [wait_type] LIKE '%io%'
--TRACEWRITE
--SQLTRACE_FILE_BUFFER
--SQLTRACE_FILE_WRITE_IO_COMPLETION
--SQLTRACE_FILE_READ_IO_COMPLETION
--SQLTRACE_LOCK
复制代码

如果没有及时取走缓冲区里面的数据,sqlserver会等待20秒,然后他将丢弃事件以释放缓存区并继续处理随后的事件

如果事件已经删除,在sqlserver里面监视TRACEWRITE等待类型,也可以发现自己是否可能收到错误信息,随着线程等待缓冲区释放空间,收到错误消息的可能性逐渐增加

 

 

因为表不支持大数据块写入,sqlserver必须逐行写入事件数据,事件开销引起的性能开销需要删除很多事件,因此sqlserver不提供跟踪向表直接写入功能

sql2005提供了alter trace权限

GRANT ALTER TRACE TO sa

 

F

sql跟踪不返回在加密存储过程,用户定义函数,视图中生成的语句文本或查询计划

要求profiler在服务器端文件保存事件时,profiler实际上同时启动了两个相同的跟踪,一个跟踪使用行集提供程序,另一个跟踪使用文件提供程序,

使用两个跟踪意味着需要双倍的开销,因此这种方法不可取

F

行集提供程序:表
文件提供程序:trc文件

F

为查询时间大于200毫秒的事件定义筛选器

F

Duration列上的筛选器值设置为大于200毫秒的跟踪结果

保存和重播跟踪

UI包装器

9个跟踪模版
TSQL_Replay模版

F

EventSequence列是一个类似于identity属性的列,在sql服务重启的时候会重置,对于每个跟踪EventSequence值是唯一的,

64位整数大小因此跟踪的事件永远不可能超过EventSequence的范围

F

trace file选项用于将数据保存到某个使用专用二进制格式的文件中trc文件

跟踪在多线程上重播

F

如果需要按顺序重播,那么选择 replay in order
如果需要重播大量跟踪,而且不在意顺序,那么选择multiple treads

F

profiler实质上只是数据库引擎功能上的一个包装器,我们不将他用于跟踪所有阶段

数据库引擎有很多功能,这些功能,api提供给profiler这个工具去调用,profiler只是包装这些功能

F

由于sql profiler用户界面需要工作流,因此在使用脚本之前必须实际启动某个跟踪,才能生成跟踪脚本

F

F

跟踪脚本使用的是微妙,而在sql profiler工具中默认使用的是毫秒

 

F

 

SELECT *
FROM sys.[fn_trace_getinfo](NULL)

复制代码
--返回跟踪事件的列名和事件名
SELECT  e.[name] AS event_name ,
        c.name AS column_name
FROM    sys.[fn_trace_geteventinfo] (2) ei
        JOIN sys.[trace_events] e ON [ei].[eventid] = e.[trace_event_id]
        JOIN sys.[trace_columns] C ON [ei].[columnid] = [C].[trace_column_id]
复制代码

 

SELECT *
FROM sys.[fn_trace_geteventinfo](NULL)

[fn_trace_geteventinfo]返回跟踪选择的事件和列的数字组合

F

服务器端跟踪和收集

EXEC sys.[sp_trace_create]
EXEC sys.[sp_trace_setevent]
EXEC sys.[sp_trace_setfilter]
EXEC sys.[sp_trace_setstatus]

-- No creation SQL available for this object type

 

sql2000删除了所有无法向后兼容的脚本

 

复制代码
--返回筛选器的信息
SELECT  [columnid] ,
        b.[name] ,
        [logical_operator] ,
        [comparison_operator] ,
        [value]
FROM    sys.[fn_trace_getfilterinfo] (2) AS a
        JOIN sys.[trace_columns] AS b ON a.[columnid] = b.[trace_column_id]
复制代码
--读取trc文件内容
SELECT *
FROM sys.[fn_trace_gettable]('C:\TEST.TRC')

 

 

查询服务器端跟踪元数据

复制代码
SELECT [status] ,
[path] ,
[max_size] ,
[buffer_count] ,
[buffer_size] ,
[event_count] ,
[dropped_event_count]
FROM sys.[traces]
WHERE id = 2
复制代码

 

F

--使用select into以最小日志记录来将trc文件里的数据插入到 testtrc表以便分析trace数据
SELECT *
INTO testtrc
FROM sys.[fn_trace_gettable]('C:\TEST.TRC')

 

EXEC sys.[sp_trace_create] @p1 OUTPUT,1,NULL,NULL,NULL
1表示打开行集提供程序

 

F

F

sqlserver profiler通过调用EXEC sys.[sp_trace_getdata] @traceid = 0, -- int
@records = 0 -- int
将这些事件从行集提供程序中取出,并执行一次pivot数据透视操作

 

行集提供程序:将跟踪数据保存到表
文件提供程序:将跟踪数据保存到trc文件

 

Microsoft.SqlServer.Management.Trace命名空间中发布了一系列管理类,帮助构建和使用行集提供程序
参看sqlserver techcenter

F

扩展事件XE

XE的主体位于sqlserver的总体层中,这种结构类似于SQLOS的角色

package0实现了包的灵活性,package0包是一个基础,他包含了和sqlserver一起发行的所有其他包需要使用的对象以及将来可能需要使用的对象

 

SecAudit的[capabilities_desc]为private,这意味着非系统使用者将无法直接使用他所包含的对象

复制代码
--查看四个包中包含的对象
--package0
--sqlos
--sqlserver
--SecAudit
SELECT *
FROM sys.[dm_xe_objects]
复制代码

F

复制代码
SELECT *
FROM sys.[dm_xe_packages]
--SQL2008 和SQL2012都发行了四个包
--package0
--sqlos
--sqlserver
--SecAudit
复制代码

 

复制代码
--sys.[dm_xe_objects]里的[package_guid]对应于 sys.[dm_xe_packages] 的[guid]
SELECT  A.[package_guid] ,
        COUNT(A.[package_guid]) AS COUNTNUM ,
        B.[guid] ,
        COUNT(B.[guid]) AS COUNTNUM ,
        B.[name]
FROM    sys.[dm_xe_objects] AS A
        JOIN sys.[dm_xe_packages] AS B ON A.[package_guid] = B.[guid]
GROUP BY A.[package_guid] ,
        B.[guid] ,
        B.[name]
复制代码

[object_type]列用于筛选特定类型的对象,跟 sys.[dm_xe_packages]一样 [capabilities_desc]列设置为private属性表示外部对象无法使用这个对象,

[description]列用于提供易读的文本来说明每个对象,目前sql2008RTM还在进一步完善该功能,因此许多对象说明还不够完整

 

描述sys.[dm_xe_objects] 中出现的各种对象类型

 

XE跟SQL跟踪一样,在通过拦截代码路径,XE提供了254个事件,而SQL跟踪提供了180个事件,很多XE事件的级别比SQL跟踪事件的级别更低,因此XE可以提供更多事件

 

例如XE可以跟踪页面拆分就激活的事件,这样用户可以在查询级别跟踪拆分,这在先前的sqlserver版本中是无法实现的

--XE还可以输出对象表的列含义
SELECT  *
FROM    sys.[dm_xe_object_columns]
WHERE   [object_name] = 'page_split';

 

[column_value]的值在运行时进行填充,如果[column_type]为data,如果[column_type]为readonly,那么列是只读的,运行时不会进行填充,

[column_type]为readonly的列是元数据,包含UUID激活事件类型的唯一标识符和version版本号,以便独立跟踪和使用每个事件的不同架构版本

事件的channel属性是和每个事件都有关的少数readonly属性之一,他反应了XE的设计目标之一是为了和event tracing for Windows(ETW)系统相统一

sql2008中的事件
管理员事件:deprecation announcement:废除声明, 例如某个功能已经被废除 ,错误报告
分析事件:分析系统性能和运行状况
调试事件:线程和进程启动和停止激活的事件,贯穿scheduler生命周期不同时期的事件,以及其他类似主题的事件
操作事件:管理sqlserver服务和数据库,数据库附加,分离,启动,停止,检测数据库页面损坏有关问题

 

 

F

[object_package_guid]和 [type_package_guid]都是16字节
655FD93F-3364-40D5-B2BA-330F7FFB6491

事件的前16字节包含一个和使用者需求无关的标识符,那么可以简单忽略这些字节,而没有必要进行处理

 

为了降低事件过度使用磁盘,XE扩展事件系统对长度可变元素数据设置了32MB的硬上限

 

和SQL跟踪一样,可以对XE事件进行筛选,并将他们路由到各种后期事件提供程序中进行收集,XE的筛选器称为谓词,而后期事件提供程序称为目标

类型和映射

XE包中可以定义两种类型:标量类型和映射类型
标量类型:单个值 ,单个整数,单个unicode字符,单个二进制大对象
映射类型:类似于编程中枚举类型

--查看系统支持的类型和映射
SELECT *
FROM sys.[dm_xe_objects] 
WHERE [object_type] IN ('type','map')
ORDER BY [object_type]
复制代码
--虽然类型可以对自身信息进行适当说明,但映射必须展示他们的相关值,以便--使用者在适当的时候可以显示易读文本
--下面查询返回sql引擎展示的所有等待类型,以及XE事件中用于说明等待使用的映射关键字(整数表示类型)

SELECT *
FROM sys.[dm_xe_map_values]
WHERE [name] = ‘wait_type’;

复制代码

F

谓词

 

pred全程:predicate 谓词

[dm_xe_objects]中的

pred_compare对象是比较函数,用于比较特定数据类型的实例
pred_source对象是扩展属性,可以在谓词中使用

复制代码
--下面查询pred_compare对象类型,通过 sys.[dm_xe_objects]返回所有可用的“>=”比较函数

SELECT *
FROM sys.[dm_xe_objects]
WHERE [object_type] = ‘pred_compare’
AND [name] LIKE ‘greater_than_equal%’

复制代码

目前只有一个谓词没有重载,就是取模运算符

 

pred_source对象,在XE系统中,事件谓词可以筛选两种类型的属性,事件自身展示的列(如sql_statement_completed事件的source_database_id列)和sys.[dm_xe_objects] DMV中定义成pred_source的任何外部属性(谓词源)

 

--查看可用的谓词源
SELECT *
FROM sys.[dm_xe_objects]
WHERE [object_type] = 'pred_source'

F

以上每种属性(sql2008RTM提供28种属性)都可以绑定到XE系统中的任何事件,并且可以随时筛选某个属性(如果事件自身的系统化负载未执行筛选该属性)

 

使用谓词源将强制XE引擎在事件处理过程中通过附加步骤获取数据,对大多数谓词而言,获取数据的开销非常小,但是如果使用多个谓词,这种开销将累加

 

操作

当事件被触发之后,你可能想在事件发生之后执行一些操作,在XE中,action就是做这样的工作
操作既可以执行代码,也可以将数据写回事件负载中,因此增加了附加属性

--在sql2008里,XE支持37种操作
SELECT *
FROM sys.[dm_xe_objects]
WHERE [object_type] ='action'

F

tsql_stack操作是一个非常有趣的适用于调试目的的操作,该操作将返回存储过程中的整个嵌套堆栈和/或导致事件激活的函数调用,

虽然返回的信息非常有用,但是,如果不短暂停止执行当前的线程和活动堆栈,tsql_stack操作将无法在引擎中获取该信息,因此和检索当前会话id相比,tsql_stack操作将承担更大的性能开销

复制代码
--有些操作不返回任何数据,仅执行外部代码,需要查看这些操作列表,可以筛选 sys.[dm_xe_objects]的[type_name]列的null返回值

SELECT *
FROM sys.[dm_xe_objects]
WHERE [object_type] = ‘action’
AND [type_name] = ‘null’

复制代码

null不同于sql null,null是package0中定义的类型名称,并显式在type类型的对象列表中

调试断点事件停止断点上触发的活动线程,并可能根据断点的触发位置阻塞整个sqlserver进程

 

目标

事件数据的目的地是一个或多个目标,系统通过目标来使用XE事件

--目标是最终的对象类型,该对象类型在ys.[dm_xe_objects]中展示元数据
SELECT  *
FROM    sys.[dm_xe_objects]
WHERE   [object_type] = 'target'

sql2008使用了13个目标(7个公有目标,6个私有目标)私有目标仅供sql审核使用

XE目标包含各种类型,他们和sql跟踪的IO提供程序有相似地方也有区别

 

etw 同步target

没有XE目标等效于SQL跟踪的行集提供程序

F

一个事件会话可以配置多个目标

 

ring_buffer:他将数据存储在一个用户可配置大小的环形缓冲区中,当环形缓冲区填充和准备覆盖以前收集的数据时,他将重新回到缓冲区的起点位置,这意味着缓冲区可以使用无限的数据量,而无需使用系统内存,但只有在特定事件才可以获取最新数据

synchronous_event_counter

bucketizer

pair_matching

sys.dm_os_ring_buffers视图在sql2005里面已经有了,所以应该不是使用扩展事件来捕获的

因为无论在sql2005还是sql2008生成的执行计划都是一样都有表值函数:sysringbuffers

事件数据缓冲区填满时,XE引擎可以采用3种可能操作,具体取决于用户如何配置事件会话
阻塞,等待缓冲区可用(无事件丢失)
删除等待事件(允许单个事件丢失) 默认模式
删除满缓存区(允许多个事件丢失)

 

中心缓存区集合(最多使用4MB内存)

 

这些设置选项不是基于每个目标的,而是针对绑定到会话的所有目标!!

F

事件会话

会话用于说明用户需要收集的事件,谓词用于解决应该筛选哪些事件,需要激活的操作和事件一起协同工作,目标在循环的结尾用于数据收集

 

和sql跟踪一样,大多数会话互相独立,连接多个会话的主要线程是中心位图,他用于指示是否启用或禁用指定事件,在许多会话中可以同步启用事件,但全局位图用于避免在运行时必须检测所有会话

 

复制代码
USE [master]
SELECT *
FROM sys.[server_event_sessions] --XE会话信息中心元数据

SELECT *
FROM sys.[server_event_sessions_events] –每个XE会话绑定的事件

SELECT *
FROM sys.[server_event_sessions_actions] –每个XE会话绑定的操作

SELECT *
FROM sys.[server_event_sessions_targets] –每个XE会话绑定的目标

SELECT *
FROM sys.[server_event_sessions_fields] –每个XE会话自定义设置信息 例如用户可以将环形缓存区的内存使用量设置为指定数量,如果使用了目标,该视图将显示内存设置

复制代码

 配置异步目标缓存区,这些设置将影响一个名为dispatcher的进程,该进程负责定期从缓冲区收集数据,并将收集的数据发送到绑定会话的每个异步目标中

 


使用sys.[dm_xe_sessions] 来监视是否存在调度异步缓存区问题

SELECT *
FROM sys.[dm_xe_sessions]

[blocked_event_fire_time]:如果使用了无事件丢失选项,该列展示了阻塞发生的时间量

F

因果跟踪

传递块

复制代码
CREATE EVENT SESSION [xe_SqlTimeouts] ON SERVER 
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(sqlserver.session_id,sqlserver.tsql_stack)),
ADD EVENT sqlserver.sql_statement_starting(
    ACTION(sqlserver.plan_handle,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_stack)) 
ADD TARGET package0.pair_matching(SET begin_event=N'sqlserver.sql_statement_starting',begin_matching_actions=N'sqlserver.session_id, sqlserver.tsql_stack',end_event=N'sqlserver.sql_statement_completed',end_matching_actions=N'sqlserver.session_id, sqlserver.tsql_stack',respond_to_memory_pressure=(0))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO
复制代码

事件的生命周期

 

F

如果用户定义了过多的事件会话,过多的action,过多的同步目标,过多的特别活跃事件,那么可能会阻塞,特别注意使用同步目标,以免出现运行时阻塞问题

 

--跟踪事件数据缓冲区 跟踪由每个活动XE会话定义的每个目标的一行,还使用[execution_duration_ms]列指示目标处理最新事件或缓存所需的事件量,如果看到该数据在逐渐增加,说明sqlserver代码路径中必然会出现等待问题
SELECT  *
FROM    sys.[dm_xe_session_targets] 

扩展事件DDL和查询

F

复制代码
--创建事件会话 CREATE EVENT SESSION允许用户创建会话和映射各种XE对象
--修改XE会话时ALTER EVENT SESSION ,会话不能处于活动状态
CREATE EVENT SESSION [statement_completed] ON SERVER
ADD EVENT sqlserver.sp_statement_completed,
ADD EVENT sqlserver.sql_statement_completed (
    ACTION ( sqlserver.sql_text )
    WHERE
  ( sqlserver.[session_id] = 60 ) )
ADD TARGET package0.ring_buffer (  SET max_memory = 4096 )
WITH (  MAX_MEMORY = 4096 KB ,
        EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS ,
        MAX_DISPATCH_LATENCY = 1 SECONDS ,
        MEMORY_PARTITION_MODE = NONE ,
        TRACK_CAUSALITY = OFF ,
        STARTUP_STATE = OFF );
复制代码

使用=运算符而没有使用pred_compare函数的原因 ,因为只有divides_by_uint64对象才需要pred_compare函数,其余情况都可以使用where 语句 and,or,() ,并支持不同条件的复杂谓词组合

复制代码
ADD TARGET package0.ring_buffer (  SET max_memory = 4096 )
WITH (  MAX_MEMORY = 4096 KB ,
        EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS ,
        MAX_DISPATCH_LATENCY = 1 SECONDS ,
        MEMORY_PARTITION_MODE = NONE ,  --CPU上的内存没有分区(因此最终我们将有3个缓冲区)并且我们没有使用因果跟踪
        TRACK_CAUSALITY = OFF ,   --TRACK_CAUSALITY 因果跟踪
        STARTUP_STATE = OFF );
复制代码
--启动会话
ALTER EVENT SESSION [statement_completed]
ON SERVER
STATE=START

 

F

--ringbuffer,bucketizer,事件统计synchronous_event_counter都在 sys.[dm_xe_session_targets]的[target_data]列保存XML格式数据,你可以使用XQuery查询数据
SELECT  *
FROM    sys.[dm_xe_session_targets] 

 

复制代码
SELECT  theNodes.event_data.value('(data/value)[1]', 'bigint') AS source_database_id ,
        theNodes.event_data.value('(data/value)[2]', 'bigint') AS object_id ,
        theNodes.event_data.value('(data/value)[3]', 'bigint') AS object_type ,
        theNodes.event_data.value('(data/value)[4]', 'bigint') AS cpu ,
        theNodes.event_data.value('(data/value)[5]', 'bigint') AS duration ,
        theNodes.event_data.value('(data/value)[6]', 'bigint') AS reads ,
        theNodes.event_data.value('(data/value)[7]', 'bigint') AS writes ,
        theNodes.event_data.value('(action/value)[1]', 'nvarchar(max)') AS sql_text
FROM    ( SELECT    CONVERT(XML, st.[target_data]) AS ring_buffer
          FROM      sys.[dm_xe_sessions] s
                    JOIN sys.[dm_xe_session_targets] st ON s.[address] = st.[event_session_address]
          WHERE     s.[name] = 'statement_completed'
        ) AS theData
        CROSS APPLY theData.ring_buffer.nodes('//RingBufferTarget/event') theNodes ( event_data );
复制代码
复制代码
source_database_id    object_id    object_type    cpu    duration    reads    writes    sql_text
7    442025160    20816    0    0    2    0    NULL
7    596895952    20816    0    0    2    0    NULL
6    322132543    20816    15    1000    2    0    NULL
5    5712692    20816    0    0    3    0    NULL
5    5712692    20816    0    0    3    0    NULL
6    801718487    20816    0    0    2    0    NULL
10    278270417    20816    0    1000    44    3    NULL
10    278270417    20816    0    0    0    0    NULL
10    90202378    20816    0    1000    45    1    NULL
10    90202378    20816    0    0    0    0    NULL
复制代码

不要停止会话否则在内存里的环形缓冲区里的数据将会清空,导致没有数据

--停止会话
ALTER EVENT SESSION [statement_completed]
ON SERVER
STATE=STOP

我觉得如果是短时间跟踪的话,可以把事件数据保持到内存,例如内存中的ring_buffer

适合突然数据库变慢等情况,短时间跟踪一下,找到问题之后就停止跟踪

 

如果是长时间跟踪,比如问题出现的时间不确定,可能在凌晨,那么这时候需要把事件数据保存到文件中

SELECT  *
FROM    sys.[dm_xe_objects]
WHERE   [object_type] = 'target'

SQL2012的异步文件目标名称叫:event_counter

 

SQL2008和SQL2012 目标对比,SQL2012多了3个目标

 

使用sys.[fn_xe_file_target_read_file]()函数从异步文件目标中读取数据,该函数返回每个事件的一行,

但你依然需要获取合适的XML格式,在event_data列展示的数据也是XML格式

SELECT  *
FROM    sys.[fn_xe_file_target_read_file]('D:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\Log',
                                          'D:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\Log',
                                          'system_health_0_130564725469520000.xel',
                                          630)

 

复制代码
SET QUOTED_IDENTIFIER OFF
SET ANSI_NULLS OFF
GO
CREATE FUNCTION sys.fn_xe_file_target_read_file (
    @path nvarchar(260), 
    @mdpath nvarchar(260),
    @initial_file_name nvarchar(260) = NULL,
    @initial_offset bigint = NULL
)
RETURNS table
AS
    RETURN SELECT *
    FROM OpenRowSet(TABLE FN_XE_READ_FILE_TARGET_FILE, @path, @mdpath, @initial_file_name, @initial_offset)
GO
复制代码

 

这里的XML是为那些希望成为XE高级用户的DBA设计的

F

--删除事件会话
DROP EVENT SESSION [statement_completed] ON SERVER 

 

 

用sql2012 连接sql2008还是没有扩展事件菜单

F

第三章 数据库和数据库文件

新建库大小5MB

F

系统数据库 master  model  tempdb msdb resource

显式静态游标和键集游标都会使用tempdb数据库

 

F

可靠消息传送的service broker也使用msdb数据库,msdb支持suspect page的修复,有未公开的跟踪标志可以删除msdb

adventurework是微软用户培训组创建的,包括AdventureWorks2008,AdventureWorksDW2008,AdventureWorksLT2008

F

AdventureWorksLT2008是AdventureWorks OLTP数据库的高度简化又不太标准的版本,他集中于具有单一架构的单一销售情况

Northwind是最初为Access开发的样例数据库

F

文件流数据文件只有逻辑和物理名称属性
一般的数据文件都有:逻辑文件名,物理文件名,初始大小,最大大小,增长增量

SELECT * FROM sys.[database_files]

 

F

F

model有53个对象:45个系统表,6个用于查询通知和service broker对象,1个用于帮助管理文件流数据的表和1个帮助管理更改跟踪的表

数据库的所有者和映射的登录帐户信息会存放在master数据库中,登录的时候就会验证

F

新建数据库时,没有指定log on,那么sqlserver会以所有数据文件之和的25%创建一个日志文件

收缩数据文件也会在数据库中产生过多的逻辑碎片

F

 

快速文件初始化

最开始的时候,无论数据文件还是日志文件都是填零初始化的,但是填零的速度很慢,那么数据文件就增加了快速初始化,

快速初始化不会实际覆盖磁盘内容,只是霸占着空间

F

自动收缩选项每30分钟收缩一次数据库,保留25%可用空间

《企业级管理实践》

DBCC SHRINKFILE都是区一级动作,他会把正在使用的区前移,把没在使用中的区从文件中移除,

但是他不会把一个区里面的空页移除,不会合并区,也不会把页面里的空间移除,合并页面
收缩数据库/收缩文件会造成更多逻辑碎片

F

数据库收缩会被快照隔离级别的事务阻挡,如果发生这种情况,DBCC SHRINKFILE和DBCC SHRINKDATABASE就会在

第一个小时内的每5分钟和之后的每个小时向错误日志写入具有信息性的消息,

sqlserver还通过SELECT * FROM sys.[dm_exec_requests]视图为shrink命令提供进程报告

 

F

 

F

 

文件流文件组 filestream文件组

F

 

复制代码
CREATE DATABASE MyMovieReviews ON PRIMARY
(NAME=Reviews_data,FILENAME='C:\DATA\Reviews_data.mdf'), FILEGROUP
    MovieReviewsFSGroup1 CONTAINS FILESTREAM
(NAME=Reviews_FS,FILENAME='C:\DATA\Review_FS') LOG ON 
(NAME=Reviews_LOG,FILENAME='C:\DATA\Reviews_log.ldf')
GO

在文件夹C:\DATA\Review_FS里会看到filestream.hdr文件和$fslog文件夹。filestream.hdr文件是filestream容器头文件,不应该修改或删除这个文件,对于现有数据库,可以用alter database添加文件流文件组

复制代码

 

F

注意:不能吧文件从一个文件组移动到另一个文件组

 

F

F

F

IAM页面跟踪in-row data,row overflow data,lob data,每种页面都会有相应的IAM进行跟踪

SELECT * FROM sys.[system_internals_allocation_units]

 

F

数据库选项

F

F

ALTER DATABASE [sss] SET RESTRICTED_USER

–可以有多个连接,但是只能来自认为是合格的用户dbcreator或sysadmin服务器角色或数据库的db_owner角色的连接

 

F

从recovery_pending切换成emergency时,sqlserver会关闭数据库,然后用特殊标志重新启动他,这样会跳过恢复过程。

跳过恢复意味着可能会有逻辑上或物理上不一致的数据,丢失索引行,断开页面链接或错误的元数据指针,

将数据库设置为emergency模式就是承认数据可能不一致但是不管怎样还是想访问他

F

ALTER DATABASE [sss] SET RESTRICTED_USER WITH ROLLBACK AFTER 
ALTER DATABASE [sss] SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE [sss] SET RESTRICTED_USER WITH no_wait

 

游标选项

F

自动选项

SQL选项

F

数据库恢复选项

F

虽然sqlserver数据库页面是8KB,但是磁盘用512byte的扇区进行I/O操作,因此,每个页面上都有16个扇区

对sql2000更改了页面校验和之后,当修改页面的时候才会写入校验和,没有修改的页面不会无端端去计算校验和

F

数据库快照

不要将快照的稀疏文件和sql2008中的稀疏列相混淆

稀疏文件总是以64KB为增量增长的,所以磁盘上的稀疏文件大小总是以64KB的倍数

F

建立快照时会记录源数据库的事务日志中同步日志序列号LSN,LSN是确定数据库中特定点的方法

使用sys.[dm_io_virtual_file_stats]() DMV对快照文件使用的空间进行统计

F

如果源数据库上有任何快照,就不能还原源数据库

F

tempdb数据库

F

用户对象:用户创建的表,临时表,表变量
内部对象:工作表,工作文件,排序单元

hash union,hash aggression,hash join
联接,聚合,联合

当sqlserver处理使用哈希运算符的查询时,使用工作文件合并或聚合数据

F

tempdb的延迟删除

F

复制代码
--使用sys.[dm_db_file_space_usage]视图来监视tempdb的空间 dbid=2
--用户对象,内部对象,版本存储
USE [tempdb]
SELECT *
FROM sys.[dm_db_file_space_usage]

SELECT *
FROM sys.[dm_db_task_space_usage]

–通常分配的空间值应该和释放的空间值相同,但是如果存在延迟删除,分配值比释放值大
SELECT *
FROM sys.[dm_db_session_space_usage]

复制代码

 

F

F

数据库安全性

--所有的登录名,不管是Windows还是sqlserver身份验证,都可以在sys.[server_principals]目录视图中看到
SELECT *
FROM sys.[server_principals]

 

F

复制代码
--下面查询显示数据库中用户映射到登录名,还显示了每个数据库用户的默认架构
SELECT  s.[name] AS loginname ,
        d.[name] AS username ,
        [default_schema_name] AS defaultschema
FROM    sys.[server_principals] s
        JOIN sys.[database_principals] d ON d.[sid] = s.[sid]
复制代码

数据和架构

主体和架构

复制代码
CREATE USER
CREATE SCHEMA 
--取代了之前的
EXEC sys.[sp_adduser] @loginame = NULL, -- sysname
@name_in_db = NULL, -- sysname
@grpname = NULL -- sysname
EXEC sys.[sp_grantdbaccess] @loginame = NULL, -- sysname
@name_in_db = NULL -- sysname
复制代码

 

F

默认架构

在sql2008中,新建数据库时,其中包括了几个架构,他们包括[INFORMATION_SCHEMA],dbo,guest

移动或复制数据库

F

drop database命令还会从实例中删除数据库的所有跟踪记录

F

sqlserver会编译一个新的日志文件,因为sp_detach_db创建的新日志文件会很小--小于1MB,所以这是收缩已经远远大于想要的日志文件的快速方法

备份,还原数据库

F

兼容性级别

F

除非将model数据库改变兼容性级别,否则sql2008中所有新建数据库的兼容级别都是100

 

--设置兼容级别
ALTER DATABASE [sss] SET COMPATIBILITY_LEVEL 100

 

F

第四章 日志记录和恢复

缓冲区管理器保证在将更改写入数据库之前,先写入事务日志

 

F

崩溃恢复,针对sqlserver重启
还原恢复,针对用户发出的restore database语句

 

recovery会在建立数据库快照,数据库镜像运行recovery

 

F

构造脏页表DPT

F

F

sys.[fn_dblog]信息更详细

复制代码
--读取事务日志
DBCC LOG([sss])

USE [sss]
SELECT * FROM sys.[fn_dblog](NULL,NULL)

DBCC LOGINFO

复制代码

无论有多少个物理日志文件,在收缩日志的时候,sqlserver不是单独考虑每个日志文件大小,而是根据整个日志确定可压缩的大小

vlf大小(31KB*8KB)

虚拟日志文件,一个0.5mb的日志文件含有两个vlf(一个vlf的最小大小是31*8kb =0.2mb)

一个vlf的最小大小是0.2MB

8KB怀疑就是一个数据页

namespace InternalsViewer.Internals.TransactionLog

Log Data containing fragment of a page at a particular offset

《sql2005 技术内幕 存储引擎》

宋沄剑的图片应该有错

F

行以物理顺序列出,FSeqNo才是真正的逻辑顺序

 

F

4400000085601161有4个VLF都是相同的证明是在同一次日志增长里的,并且loginfo里没有其他的createLSN说明

事务日志只增长过一次

F

F

自动截断日志
将恢复模式设置为simple
从未进行过完整备份

F

sqlserver根据每分钟内可恢复10MB事务日志的估算来确定恢复间隔

用户线程调用日志管理器,日志管理器都会检查日志大小

如果数据库在自动截断模式时日志已达到70%,那么日志管理器会唤醒checkpoint线程

F

--查看 sys.[database_recovery_status] 视图的[last_log_backup_lsn]列,如果该列为空,数据库就是处于自动截断模式

SELECT *
FROM sys.[database_recovery_status]
WHERE [database_id]=DB_ID(‘sss’)

进行数据库完整备份前

进行数据库完整备份之后

设置数据库为简单恢复模式之后,[last_log_backup_lsn]值变成null

ALTER DATABASE [sss] SET RECOVERY SIMPLE

F

压缩日志

auto_shrink选项每30分钟运行自动压缩进程,日志管理器累计自动压缩进程之间的30分钟间隔内所使用的最大日志空间量的统计信息,自动压缩进程将日志的压缩点标记为实际使用的最大日志空间的125%和日志的最小大小这两个数中较大的那个(最小大小是创建日志时的大小或已经被手动增大或压缩过的大小),如果有机会(备份并截断)的话,日志就会被压缩到这个大小

F

复制代码
--统计各个数据库的事务日志文件已使用的百分比
SELECT  [instance_name] AS 'DATABASE' ,
        [cntr_value] AS 'LogFullPct'
FROM    sys.[dm_os_performance_counters]
WHERE   [counter_name] LIKE 'percent log used%'
        AND [instance_name] NOT IN ( '_total', 'mssqlsystemresource', 'MASTER',
                                     'MODEL', 'TEMPDB', 'MSDB', 'ReportServer',
                                     'ReportServerTempDB' )
        AND [cntr_value] > 0
-- Author:      <桦仔>
-- Blog:        <http://www.cnblogs.com/lyhabc/>
-- Create date: <2014/4/18>
-- Description: <统计各个数据库的总大小V2 不包含数据文件>
-- =============================================
SET NOCOUNT ON 
USE master
GO

DECLARE @DBNAME NVARCHAR(MAX)
DECLARE @SQL NVARCHAR(MAX)

–临时表保存数据
CREATE TABLE #DataBaseServerData
(
ID INT IDENTITY(1, 1) ,
DBNAME NVARCHAR(MAX) ,
Log_Total_MB DECIMAL(18, 1) NOT NULL ,
Log_FREE_SPACE_MB DECIMAL(18, 1) NOT NULL
)

–游标
DECLARE @itemCur CURSOR
SET
@itemCur = CURSOR FOR
SELECT name from SYS.[sysdatabases] WHERE [name] NOT IN (‘MASTER’,‘MODEL’,‘TEMPDB’,‘MSDB’,‘ReportServer’,‘ReportServerTempDB’)
AND [status]=65544

OPEN @itemCur
FETCH NEXT FROM @itemCur INTO @DBNAME
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL=N’USE [’+@DBNAME+’];’+CHAR(10)
+
‘INSERT [#DataBaseServerData]
( [DBNAME] ,
[Log_Total_MB] ,
[Log_FREE_SPACE_MB ]
)
SELECT ‘’’+@DBNAME+’’’, str(sum(convert(dec(17,2),sysfiles.size)) / 128,10,2) AS Total_MB,
SUM(( database_files.size - FILEPROPERTY(database_files.name, ‘‘SpaceUsed’’) )) / 128.0 AS free_space_mb
FROM dbo.sysfiles as sysfiles INNER JOIN sys.database_files as database_files ON sysfiles.[fileid]=database_files.[file_id] WHERE sysfiles.[groupid] =0
AND database_files.[type] = 1;’
EXEC (@SQL)
FETCH NEXT FROM @itemCur INTO @DBNAME
END

CLOSE @itemCur
DEALLOCATE @itemCur

SELECT * FROM [#DataBaseServerData]
DROP TABLE [#DataBaseServerData]

复制代码

备份和还原数据库

 

sql2008主要有4种备份类型:
完整备份
差异备份
日志备份
文件和文件组备份

F

备份线程只复制区

sql2008还支持一个日志标记的功能,他能让你在事务日志中放置参考点,如果数据库处于full模式,可以选择恢复到这些日志的标记之一

http://technet.microsoft.com/zh-cn/library/ms186865(SQL.105).aspx

http://msdn.microsoft.com/en-us/library/ms186858.aspx

F

最小日志记录只记录那些需要回滚事务的信息,但不支持时间点恢复
批量操作如下
select into
bulk insert
openrowset(bulk..)
insert into select
部分更新具有lob数据类型的列
update xx write
writetext,updatetext
create index
alter index rebuild 或 dbcc reindex
drop index

BCM BULK CHANGED MAP也称为最小记录映射ML MAP

最小化记录的缺点:sqlserver会强制在事务提交之前将数据页刷到磁盘,尤其这些页面的IO为随机IO,强制刷数据页面可能会非常昂贵,可以将他们与完整记录相比较,完整记录总是顺序IO,如果没有快速IO子系统的话,可能会很明显感觉最小记录比完整记录慢

由于在事务提交之前就要将数据刷到磁盘,那么就需要调用eager writer勤奋写入器不停刷盘

以insert select 为例,首先插入 insert select  top(10000)  是一个大事务

新页面以最小日志记录,数据不会不停刷盘,如果这时候宕机,我还没有提交事务,那么sqlserver只需要在下次启动的时候

将已经刷盘的页面释放掉就可以了,如果不是宕机是rollback tran也是同样的道理

纵观下面的大容量操作命令,你会发现都是插入操作新建索引操作,这些操作都是同样的道理,预先刷盘,回滚的时候就释放页面

select into
bulk insert
openrowset(bulk..)
insert into select
部分更新具有lob数据类型的列
update xx write
writetext,updatetext
create index
alter index rebuild 或 dbcc reindex
drop index

 

truncate命令除外

 

 

大容量日志模式下的大批量操作,会把数据放进去日志备份文件bak里面,因为不像完整模式,每条记录都有前影像和后影像

所有只能把大批量操作期间的数据放进去日志备份文件,从而导致

大容量日志模式下的大批量操作备份出来的日志文件比在full模式下的大批量操作备份出来的日志文件大

F

F

F

F

sqlserver可能需要在恢复完成后对元数据做些调整,所以直到完成恢复的所有阶段,才允许访问数据库,换言之,restore没有“快速”恢复这个选项

F

页面还原 ,suspect page msdb

使用页面还原之后必须进行日志还原,不是所有的已损坏页都可以用数据库联机还原

企业版才支持联机页面还原

F

在单个文件中可以还原的最多页数是1000

SELECT [redo_target_lsn]

FROM sys.[master_files]
WHERE [database_id]=5

 

with standby还原

必须用 with recovery还原最后一个日志(不会保存备用文件standby文件),才能让数据库完全可用

F

F

第五章 表

在一个真实的关系数据库中,表中的每一行都是唯一的并具有一个被称为主键的唯一标识符(与ANSI SQL标准相一致,sqlserver不需要你是一行唯一或声明一个主键,但是由于这两个概念对关系模型非常关键,因此建议你总是这样做)

F

兼容性视图也可以通过dbo架构访问,因此sys.sysobjects和dbo.sysobjects是同一个对象,对于分类视图和动态关联对象来说,必须指定sys架构来访问对象

F

--name在任何情况下都合法
CREATE TABLE [dbo].customer([name] CHAR(30))

 

F

--可以看一下会话是否有开启 [quoted_identifier]
SELECT  [quoted_identifier]
FROM    sys.[dm_exec_sessions]
WHERE   [session_id] = @@SPID

 

F

F

sql2005 sp2允许小数点之后的数据存放在可变空间中
sql2008默认为表除了master,model,tempdb,msdb之外的所有数据库启用了vardecimal storage format属性
虽然vardecimal存储格式可以降低数据的存储容量,但是却增加了额外的CPU开销为代价,一旦启用某个表的vardecimal属性,则表中所有decimal数据都存储为可变长度

vardecimal storage format属性是一种脱机操作,sqlserver独占锁定正在修改的表,直到所有decimal数据转换成新的格式。vardecimal存储格式已经不推荐使用了,因此我们不会介绍vardecimal数据的内部存储,对于新开发,建议使用sqlserver的压缩功能使可变字节的存储需求降到最低

F

日期和时间数据类型

F

date为3字节正数
所有包含时间信息的数据类型(time,datetime2,datetimeoffset)都允许在数据类型后添加一个1~7之间的数字来表示所保留字的方式来指定时间部分的精度,如果不指定精度,默认为7

复制代码
SELECT CAST(CURRENT_TIMESTAMP AS TIME)
SELECT CAST(CURRENT_TIMESTAMP AS TIME(2))
SELECT CAST(CURRENT_TIMESTAMP AS TIME(7))
--08:46:30.7200000
--08:46:30.73
--08:46:30.7300000
复制代码

 

F

字符数据类型

复制代码
SELECT [name],[max_length] FROM sys.[types]
name    max_length
image    16
text    16
uniqueidentifier    16
date    3
time    5
datetime2    8
datetimeoffset    10
tinyint    1
smallint    2
int    4
smalldatetime    4
real    4
money    8
datetime    8
float    8
sql_variant    8016
ntext    16
bit    1
decimal    17
numeric    17
smallmoney    4
bigint    8
hierarchyid    892
geometry    -1
geography    -1
varbinary    8000
varchar    8000
binary    8000
char    8000
timestamp    8
nvarchar    8000
nchar    8000
xml    -1
sysname    256
复制代码

 

F

F

字符数据排序规则

sqlserver的系统表也遵守排序规则

resource数据库使用Latin1_General_CI_AI排序规则

F

SELECT * FROM sys.[fn_helpcollations]()
--3885种排序规则,112种排序规则被废弃 SQL2012

由于排序规则决定数据在索引中出现的顺序,因此sqlserver不会接受由于你将数据库移动到不同的Windows版本上而造成的对排序规则变化的定义

Windows排序规则以族的形式出现,每族有18种排序规则,这18种主要是CI,BIN,AI,KS 假名,全半角,重音,二进制的不同

F

旧的排序规则是建立在Windows2000排序规则上的,而新的_100排序规则是建立在Windows2008中的排序规则基础上的 Latin1_General_100(sql2008)和Latin1_General(sql2000)是排序规则对

如果从sql2005用linked server链接sql2008,则应该避免使用新的_100排序规则,否则在访问时会遇到
非法的表格数据流排序规则错误TDS

F

--查看某种排序规则的代码页
SELECT COLLATIONPROPERTY('Latin1_General_CS_AS','CODEPAGE') AS '排序规则代码页'
--排序规则代码页
--1252

不要使用仅支持unicode的排序规则作为服务器排序规则!!!

SELECT RANK=DENSE_RANK() OVER(ORDER BY colatedwork)

F

F

二进制排序规则,不存在二级权值,字符按照字符集中的代码点排序,因此使用前面实例中的Latin_General_BIN2

二进制排序,大写字母排在小写字母前面,这是ASCII标准

F

BIN是早期的二进制排序规则
BIN2是新的二进制排序规则,开发的时候尽量使用BIN2

转换称varbinary变成4100,这是因为PC架构是从小到大的,即最不重要的字节会存储在最前面

SQLSERVER排序规则有76种,其中1种被废弃

从sys.[fn_helpcollations]()看到SQL排序规则和哪种Windows排序规则相匹配

F

F

tertiary weights函数计算三级权重,然后重新排序

F

安装sqlserver时定义的排序规则,如果选择错了,必须重装sqlserver

在复选框里,binary提供BIN二进制排序,而binary-code point提供BIN2 二进制排序

F

F

使用sqlserver排序规则的陷阱
char,varchar数据类型优先级比nchar,nvarchar低,因此列转换成value类型,这种情况下可以使用索引

如果你使用SQL排序规则,不要混用varchar和nvarchar

如果列是nvarchar类型,则必须强制一种二进制排序规则,但是只有当用户能够接受一种区分大小写的查询时才可以

F

特殊数据类型

sql_variant数据类型可以保存除了text,ntext,image,xml,用户定义类型,max的可变长度,rowversion之外的任何数据类型

空间数据类型 sql2008提供了两种数据类型用于存储空间数据,geometry数据类型支持平面或欧几里德数据
geometry数据类型和sql标准版本1.1.0的开放地理信息联盟简单特性相一致,geography数据类型存储椭圆数据
例如全球卫星定位的经度和维度坐标,这些数据类型具有自己的访问和操作数据方法,也有自己特殊的扩展所有架构

F

SELECT ROWGUIDCOL FROM [dbo].[customer]

 

F

SELECT GETANSINULL('sss') 函数确定当前会话的默认可空性,当新列允许空值或该列或数据类型为空而且在表被创建或修改没有明确定义时,该函数返回1,强烈建议在建表时设置列为null或not null,这样可以消除二义性,同时可以保证你控制表的构建方式

F

sql2008引入了稀疏列的概念,当数据库允许很多列和很多行中存在null值,稀疏列通过利用更多的系统开销来检索not null值,从而降低null值的空间需求,因此当大部分数据都为null时,就可以体现出稀疏列的强大

用户定义数据类型

F

F

F

SELECT IDENTITYCOL FROM [dbo].[customer]

 

F

F

SELECT * FROM [INFORMATION_SCHEMA].[COLUMNS]
SELECT [ORDINAL_POSITION] FROM [INFORMATION_SCHEMA].[COLUMNS]

提供[ORDINAL_POSITION]值显示列的原始位置,因此column_id不一定是该列的顺序位置,如果删除了某一列或添加了某一列

在sql2008中兼容性视图sys.sysindexes包含很多相同的信息,但是由于sql2005中引入的存储结构变化,因此他是不完整的

F

indexid在2~250或256~1005之间(251~255的值保留)由于一张表可以有999个非聚集索引

SELECT * FROM sys.[xml_indexes] XML索引

SELECT [hobt_id],[partition_id] FROM sys.[partitions] 里的[hobt_id]和[partition_id] 之间有一对一关系

F

复制代码
SELECT  OBJECT_NAME(p.[object_id]) AS NAME ,
        p.[partition_id] ,
        p.[partition_number] AS pnum ,
        p.[rows] ,
        a.[allocation_unit_id] AS au_id ,
        a.[type_desc] AS page_type_desc ,
        a.[total_pages] AS pages
FROM    sys.[partitions] p
        JOIN sys.[allocation_units] a ON p.[partition_id] = a.[container_id]
WHERE   [object_id] = OBJECT_ID('customer')
复制代码

 

F

复制代码
SELECT  CONVERT(CHAR(8), OBJECT_NAME(i.object_id)) AS tablename ,
        *
FROM    sys.[indexes] AS i
        INNER JOIN sys.[partitions] AS p ON [p].[object_id] = [i].[object_id]
                                            AND [p].[index_id] = [i].[index_id]
        INNER JOIN [sys].[system_internals_allocation_units] AS a ON a.[container_id] = [p].[partition_id]
ORDER BY [i].[object_id]
复制代码

 

F

数据页面

行偏移数组:看上去是数组形式,实际上是按顺序排列,定义行边界 (数组里的每个元素占用2字节)

数据页面头解释

metadata:该页所在对象ID
metadata:该页所在分区ID
metadata:该页所在分配单元的ID ,交换分区时候需要修改这个分配单元ID
freedata:该页面中的第一个可用空间的字节偏移量
Pminlen:行的固定长度部分的字节数
tornBits:一共有16个位 2字节:每位保存每个扇区的一位
fagBits:包含关于页面其他信息的2字节位图

F

F

想一下内存中的存储桶页面头部的buffer和hash存储桶肯定存在某种关联,然后使用key-value来查找存储桶中的页面


BUF @0x00000002708D36C0

bpage = 0x000000026BBE8000

buf和bpage都不是指向数据页面的物理地址

在vs里面找不到

F

F

数据行结构:只要数据是以非压缩形式存储的,我们将这种格式称为FixedVar格式

状态B字段中只使用一位,表示该记录是一条备份转发记录

F

F

F

复制代码
CREATE FUNCTION convert_page_nums(@page_num binary(6))
RETURNS VARCHAR(11)
AS 
BEGIN
    RETURN(
        CONVERT(VARCHAR(2),(
                CONVERT(INT,SUBSTRING(@page_num,6,1))* POWER(2,8)
            ) +
            (CONVERT(INT,SUBSTRING(@page_num,5,1)))
        ) + ':' +
        CONVERT(VARCHAR(11),
            (CONVERT(INT,SUBSTRING(@page_num,4,1)) * POWER(2,24)) + 
            (CONVERT(INT,SUBSTRING(@page_num,3,1)) * POWER(2,16)) +
            (CONVERT(INT,SUBSTRING(@page_num,2,1)) * POWER(2,8))  +
            (CONVERT(INT,SUBSTRING(@page_num,1,1)))
        )
    )
END

SELECT dbo.convert_page_nums(0x6E0000000100);
–SQL Server:将6字节的十六进制页面号转化成【文件号:页面号】格式函数

–http://www.cnblogs.com/xbf321/archive/2009/09/12/1565291.html

复制代码

 

--使用未记录函数 sys.fn_PhysLocFormatter和一个未记录值%%physloc%%来返回结果行中的物理位置和表中的数据值
SELECT sys.fn_PhysLocFormatter(%%physloc%%) AS RID ,* FROM CUSTOMER
--RID    city    region
--(1:79:0)    1    2

%%physloc%%值不是关系引擎所能理解的,也就是在where子句中使用%%physloc%%,则sqlserver必须要检查哪些行位于%%physloc%%所指示的页面上,不能使用%%physloc%%来查找行,%%physloc%%作为sqlserver产品开发小组的一种调试功能而引入,不打算在产品应用程序中使用

F

F

复制代码
SELECT minlen,maxlen FROM sysindexes minlen,maxlen只能在兼容性视图sysindexes里查询,所有目录视图也查不到
indexproperty()函数返回minlen值等于列长度( sys.COLUMNS 的max_length)加上4字节的和,其中不包括用于存储列数目的2字节,也不包括null位图

SELECT minlen ,
maxlen
FROM sys.sysindexes
WHERE id=OBJECT_ID(‘customer’)

SELECT INDEXPROPERTY(OBJECT_ID(‘customer’), NULL, ‘minlen’) AS ‘最小列长度’

SELECT max_length+4 FROM sys.COLUMNS

复制代码

 

F

syscolumn不再可靠

复制代码
SELECT  c.[name] AS columnname ,
        c.[column_id] ,
        pc.[max_inrow_length] ,
        [pc].[system_type_id] ,
        [pc].[leaf_offset]
FROM    sys.[system_internals_partition_columns] pc
        JOIN sys.[partitions] p ON p.[partition_id] = pc.[partition_id]
        JOIN sys.[columns] c ON [column_id] = [partition_column_id]
                                AND c.[object_id] = p.[object_id]
WHERE   p.[object_id] = OBJECT_ID('aa') 
复制代码

F

F

第一可变长度列  第二可变长度列  第三可变长度列

可变长度列偏移的长度

201

F

 

01111111110
从右到左
col10  col9 。。。。。id
‘a’      null                1

11111111100
从右到左
1 0 0
col10。。。。。 col1    id

                       ‘b’      2

F

F

日期和时间数据的存储

对于datetime和smalldatetime数据类型来说,日期值均被存储为0

F

对于datetimeoffset数据的列用2个字节存储timezone偏移,之所以用2字节是因为偏移量被存储为协调世界时UTC的小时和分钟数每部分一个字节

F

各种日期和时间制的转换

sql_variant数据类型存储

F

F

F

保证实体完整性要有主键

F

F

F

重建一张表或一个分区以修改压缩设置或删除碎片

被修改的列不能是text,image,ntext,rowversion,timestamp列

F

添加一个新列 with values

F

F

启用或禁用触发器

删除某一列时不会回收磁盘空间,除非你在表上建立聚集索引或重建聚集索引的方式回收空间

添加允许null的新列时,sqlserver修改只能是元数据操作

F

复制代码
USE [sss]
CREATE TABLE change
    (
      col1 SMALLINT ,
      col2 CHAR(10) ,
      col3 CHAR(5)
    )

SELECT c.[name] AS column_name ,
c.[column_id] ,
pc.[max_inrow_length] ,
pc.[system_type_id] ,
pc.[leaf_offset]
FROM sys.[system_internals_partition_columns] pc
JOIN sys.[partitions] p ON p.[partition_id] = [pc].[partition_id]
JOIN sys.[columns] c ON [column_id] = pc.[partition_column_id]
AND c.[object_id] = p.[object_id]
WHERE p.[object_id] = OBJECT_ID(‘change’)

–将smallint修改为int
ALTER TABLE change ALTER COLUMN col1 INT

–col1的位置值在行的更后面,偏移量4处没有任何行
SELECT c.[name] AS column_name ,
c.[column_id] ,
pc.[max_inrow_length] ,
pc.[system_type_id] ,
pc.[leaf_offset]
FROM sys.[system_internals_partition_columns] pc
JOIN sys.[partitions] p ON p.[partition_id] = [pc].[partition_id]
JOIN sys.[columns] c ON [column_id] = pc.[partition_column_id]
AND c.[object_id] = p.[object_id]
WHERE p.[object_id] <span style="c

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页