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 )
相關文章
相關標籤/搜索