SQL知识整理二:锁、游标、索引

数据库

  锁的模式 服务器

锁模式架构

描述并发

共享(S)性能

用于不更改或不更新数据(只读操做),如SELECT语句fetch

更新(U)spa

用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。线程

排它(X)设计

用于数据修改操做,例如INSERT、UPDATE或DELETE。确保不会同时对同一资源进行多重更新指针

意向

SQL Server有在资源的低层得到共享锁或排它锁的意向意向锁的类型为:意向共享(IS)、意向排它(IX)以及意向排它共享(SIX)

架构

在执行依赖于表架构的操做时使用。架构锁的类型为:架构修改(Sch-M)和架构稳定(Sch-S)

大容量更新(BU)

向表中大容量复制数据并指定了TABLOCK提示时使用

    死锁 死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其余进程所站用不会释放的资源而处于的一种永久等待状态。

  死锁的四个必要条件

    互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
    请求与保持条件(Hold and wait):已经获得资源的进程能够再次申请新的资源。
    非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
    循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每一个进程都在等待相邻进程正占用的资源

  死锁的处理方法

    查看那个spid处于wait状态,而后用kill spid来干掉(即破坏死锁的第四个必要条件:循环等待)。
    使用SET LOCK_TIMEOUT timeout_period(单位为毫秒)来设定锁请求超时。默认状况下,数据库没有超时期限(timeout_period值为-1,能够用SELECT @@LOCK_TIMEOUT来查看该值,即无限期等待)。
    SQL Server内部有一个锁监视器线程执行死锁检查,锁监视器对特定线程启动死锁搜索,检测到死锁后,数据库引擎选择运行回滚开销最小的事务的会话做为死锁牺牲品回滚死锁牺牲品的事务并释放该事务持有的全部锁,使其余线程的事务能够请求资源并继续运行。  

 

游标

  游标定义:

    能够对一个select的结果集进行处理,或是不须要所有处理,就会返回一个对记录集进行处理以后的结果。

    游标其实是一种能从多条数据记录的结果集中每次提取一条记录的机制。游标能够完成:

    # 容许定位到结果集中的特定行

    # 从结果集的当前位置检索一行或多行数据

    # 支持对结果集中当前位置的进行修改

    因为游标是将记录集进行一条条的操做,因此这样给服务器增长负担,通常在操做复杂的结果集的状况下,才使用游标。SQL Server 2005有三种游标:T-SQL游标、API游标、客户端游标。

  游标的基本操做

    游标的基本操做有定义游标、打开游标、循环读取游标、关闭游标、删除游标。

  A、 定义游标

declare cursor_name    --游标名称
cursor [local | global]    --全局、局部
[forward only | scroll]    --游标滚动方式
[read_only | scroll_locks | optimistic]    --读取方式
for select_statements                    --查询语句
[for update | of column_name ...]        --修改字段

 

  参数:

    forward only | scroll:前一个参数,游标只能向后移动;后一个参数,游标能够随意移动

    read_only:只读游标

    scroll_locks:游标锁定,游标在读取时,数据库会将该记录锁定,以便游标完成对记录的操做

    optimistic:该参数不会锁定游标;此时,若是记录被读入游标后,对游标进行更新或删除不会超过

  B、 打开游标

    open cursor_name;

    游标打开后,可使用全局变量@@cursor_rows显示读取记录条数

  C、 检索游标

fetch cursor_name;

检索方式以下:

fetch first; 读取第一行

fetch next; 读取下一行

fetch prior; 读取上一行

fetch last; 读取最后一行

fetch absolute n; 读取某一行

若是n为正整数,则读取第n条记录

若是n为负数,则倒数提取第n条记录

若是n为,则不读取任何记录

fetch pelative n

若是n为正整数,则读取上次读取记录以后第n条记录

若是n为负数,则读取上次读取记录以前第n条记录

若是n为,则读取上次读取的记录

  D、 关闭游标

    close cursor_name;

  E、 删除游标

    deallocate cursor_name;

  游标操做示例

--建立一个游标
declare cursor_stu cursor scroll for
    select id, name, age from student;
--打开游标
open cursor_stu;
--存储读取的值
declare @id int,
        @name nvarchar(20),
        @age varchar(20);
--读取第一条记录
fetch first from cursor_stu into @id, @name, @age;
--循环读取游标记录
print '读取的数据以下:';
--全局变量
while (@@fetch_status = 0)
begin
    print '编号:' + convert(char(5), @id) + ', 名称:' + @name + ', 类型:' + @age;
    --继续读取下一条记录
    fetch next from cursor_stu into @id, @name, @age;
end
--关闭游标
close area_cursor;

--删除游标
--deallocate area_cursor;

                                索引

  汇集索引定义:

         聚簇索引即创建在聚簇上的索引,建立聚簇索引时,须要对已有表数据从新进行排序(若表中已有数据),即删除原始的表数据后再将排序结果按物理顺序插回,故聚簇索引创建完毕后,创建聚簇索引的列中的数据已经所有按序排列。
        一个表中只能包含一个聚簇索引,但该索引能够包含多个列。

        B-树索引中,聚簇索引的叶层就是数据页。

  汇集索引最佳实践:

    首先建立汇集索引

    汇集索引键最好是惟一值

    汇集索引上的列须要足够短,检索必定范围和预先排序数据时使用,由于汇集索引的叶子与数据页面相同,索引顺序也是数据物理顺序,读取数据时,磁头是按照顺序读取,而不是随机定位读取数据

    在频繁更新的列上不要设计汇集索引,他将致使全部的非汇集全部的更新,阻塞非汇集索引的查询

    不要使用太长的关键字,由于非汇集索引实际包含了汇集索引值

    不要在太多并发度高的顺序插入,这将致使页面分割,设置合理的填充因子是个不错的选择

  汇集索引示例:

CREATE CLUSTERED INDEX IX_tb_heap_test_id

ON dbo.tb_heap_test

(id)

WITH (ONLINE=ON)

  非汇集索引定义:

        非聚簇索引相似书本索引,索引与数据存放在不一样的物理区域,创建非聚簇索引时数据自己不进行排序。一个表中科含多个非聚簇索引。
        B-树索引中,非聚簇索引的叶层还是索引页,其以指针指向数据页实际存储位置。

  非汇集索引最佳实践

    频繁更新的列,不适合作汇集索引,但能够作非汇集索引

    宽关键字,例如很宽的一列或者一组列,不适合作汇集索引的列可做非汇集索引列

    检索大量的行不宜作非汇集索引,可是可使用覆盖索引来消除这种影响

 

  非汇集索引示例:

CREATE INDEX IX_tb_clustered_update_ID

ON  dbo.tb_clustered_update 

(ID)

WITH (ONLINE=ON)

 

  非汇集与汇集用法之比较

    检索的数据行

            通常地,检索数据量大的通常使用汇集索引,由于汇集索引的叶子页面与数据页面在相同。相反,检索少许的数据可能非汇集索引更有利,但注意书签查找消耗资源的力度,不过可考虑覆盖索引解决这个问题。

    数据是否排序

            若是数据须要预先排序,须要使用汇集索引,若不须要预先排序就那就选择汇集索引。

    索引键的宽度

            索引键若是太宽,不只会影响数据查询性能,还影响非汇集索引,所以,若索引键比较小,能够做为汇集索引,若是索引键够大,考虑非汇集索引,若是很大的话,能够用INCLUDE建立覆盖索引

    列更新的频度

            列更新频率高的话,应该避免考虑所用非汇集索引,不然可考虑汇集索引。

    书签查找开销

            若是书签查找开销较大,应该考虑汇集索引,不然可以使用非汇集索引,更佳是使用覆盖索引,不过得根据具体的查询语句而看

 

  覆盖索引

        覆盖索引可显著减小查询的逻辑读次数,使用INCLUDE语句添加列的方式更容易实现,他不只减少索引中索引列的数据,还能够减小索引键的大小,缘由是包含列只保存在索引的叶子级别上,而不是索引的叶子页面。覆盖索引充当一个伪的汇集索引。覆盖索引还可以有效的减小阻塞和死锁的发生,与汇集索引相似,由于汇集索引值发生一次锁,非覆盖索引可能发生两次,一次锁数据,一次锁索引,以确保数据的一致性。覆盖索引至关于数据的一个拷贝,与数据页面隔离,所以也只发生一次锁。

 

  覆盖索引示例:

CREATE INDEX IX_IX_tb_booklookup_name_type_other

ON dbo.tb_booklookup

(name)

INCLUDE

([type],other)

WITH ( ONLINE=ON )
相关文章
相关标签/搜索