2015-12-03
瞿锴
产业园
SQL SERVER资源
CPU:资源调度及运算工作
内存/磁盘:数据存储及交互
锁:控制资源占用冲突
缓存池
1、执行计划缓存
SQL SERVER拿到一个SQL语句,先分析生成一个执行计划。一个SQL语句对应多个执行计划,分析则其最优者执行。
每一个SQL对应一个Hash值,参数化的SQL使用同一个执行计划缓存
即席优化(表数据变化比较频繁时)开启,可提升执行计划缓存效率。
2、数据缓存
数据页和索引页的映射
逻辑读:读内存上的数据
物理读:读磁盘上的数据
预读:
页:1页有8K数据
区:1个区有8页数据
在读区里某页的数据时,会顺带把这个页所在区的其他7个页的数据页都读出来,这就是预读,为了减少I/O的次数
索引进阶
SQL最小数据单位:数据页
行偏移:
统计信息:
1、在一个空表中有数据的改动
(空表没有统计信息)
2、当统计信息创建时,表的行数只有500或以下,且后来统计对象中的引导列(统计信息的第一个字段的数据)的更改次数>500
(第一次去查表中的数据时,表才有统计信息)
3、当统计信息创建时,表的行数超过500行,且统计对象中的引导列的更改次数>500+总行数的20%
(变动大于500时会更新统计信息)
归档的必要性:减少数据量,统计信息更快更准确些
特殊条件:需要特殊查询触发
索引碎片:
1页=8Kb
1区=联系的8页
变长子段的存在—>索引碎片
页分裂:插入数据导致分裂;数据长度增加导致分裂
也分裂会导致更多的I/O量,至少4个页的信息要更改
避免方法:
(1)填充因子——DBA做的
(2)提前在页中空出空间
这两种做法都会导致数据页的数量增加,从而导致I/O的量也增加
SQL执行流程
从后往前看,从上往下看
锁
加了with(nolock)会避免排它锁和共享锁不兼容的问题
锁颗粒度:
行锁/键锁(键锁是最经济的锁)
页锁
表锁
库锁
每个锁占用96个字节的内存空间
锁升级:
行锁/键锁->表锁
页锁->表锁
PS:从级别上讲,行锁和页锁是一个级别的
update没办法加with(nolock)
解决办法:减少单次更新的数据量
事务
原子性:要么同时成功,要么同时失败;
一致性:约束或触发器也一致;
隔离性:单个事务执行期间,其余事务无法访问中间状态;
持久性:事务一旦提交成功,数据一定存在
事务隔离级别:
- 脏读:一个事务读取了另一个事务未提交的数据
SQL语句加了with(nolock),是为了提高并发时的性能,但是为导致脏读问题,详见SQL Server 中WITH (NOLOCK)浅析 - 不可重复读:一个事务范围内,两个相同的查询返回了不同数据
(没有Go的都算一个事务) - 幻影读
悲观并发控制:
- 未提交读
- 提交读
- 重复读:S锁的时间持续整个事务而不是逐行
- 序列化:Range Lock,避免幻影读,银行常用