西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁西西教程數(shù)據(jù)庫教程 → SQL SERVER 索引中聚集索引分析和Transact-SQL語句優(yōu)化

SQL SERVER 索引中聚集索引分析和Transact-SQL語句優(yōu)化

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:本站整理時(shí)間:2010/9/17 23:43:18字體大小:A-A+

作者:佚名點(diǎn)擊:599次評論:1次標(biāo)簽: SQL 索引

  • 類型:音頻處理大。1M語言:中文 評分:5.1
  • 標(biāo)簽:
立即下載

寫這篇文章幫助自己更好的理解索引,也算是自己的學(xué)習(xí)筆記吧,分享給大家 ,文中如果有分析的不正確的地方,歡迎指出 。
一. 聚集索引B樹分析
1.聚集索引按B樹結(jié)構(gòu)進(jìn)行組織的,索引B樹種的每一頁稱為一個(gè)索引節(jié)點(diǎn)。B樹的頂端節(jié)點(diǎn)稱為根節(jié)點(diǎn)。
  索引中的低層節(jié)點(diǎn)稱為葉節(jié)點(diǎn)。根節(jié)點(diǎn)與葉節(jié)點(diǎn)之間的任何索引級別統(tǒng)稱為中間級。在聚集索引中,葉節(jié)點(diǎn)包含基礎(chǔ)表的數(shù)據(jù)頁。
  根節(jié)點(diǎn)和中間級節(jié)點(diǎn)包含存有索引行的索引頁。每個(gè)索引行包含一個(gè)鍵值和一個(gè)指針,該指針指向 B 樹上的某一中間級頁或葉級索引中的某個(gè)數(shù)據(jù)行.每級索引中的頁均被連接在雙向鏈接列表中。
 
2.索引使用的每一個(gè)分區(qū)的index_id = 1 ,默認(rèn)情況下聚集索引單個(gè)分區(qū),當(dāng)使用分區(qū)表的時(shí)候,每個(gè)分區(qū)都有一個(gè)包含該特定分區(qū)相關(guān)數(shù)據(jù)的B樹結(jié)構(gòu),我是這么理解的不知道對不對?
 
3.SQL Server 寫入的數(shù)據(jù),數(shù)據(jù)鏈內(nèi)的頁和行將按聚集索引鍵值進(jìn)行排序。
 
4.SQL Server 將在索引中查找該范圍的起始鍵值,然后用向前或向后在數(shù)據(jù)頁中進(jìn)行掃描。為了查找數(shù)據(jù)頁鏈的首頁,SQL Server 將從索引的根節(jié)點(diǎn)沿最左邊的指針進(jìn)行掃描。
 
 聚集索引B樹圖 :
 
 
二 .優(yōu)化 Transact-SQL 語句經(jīng)常使用的語句
  
 1.SET STATISTICS IO {ON| OFF} /*Transact-SQL 語句生成的磁盤活動量的信息*/
  
 2.SET SHOWPLAN_ALL ON {ON| OFF} /*返回有關(guān)語句執(zhí)行情況的詳細(xì)信息,并估計(jì)語句對資源的需求*/
 
 3.SET STATISTICS TIME {ON| OFF} /*顯示分析、編譯和執(zhí)行各語句所需的毫秒數(shù)*/
 
  4.使用T-SQL語句創(chuàng)建索引的語法:
    CREATE [UNIQUE] [CLUSTERED|NONCLUSTERED] 
    INDEX   index_name
    ON table_name (column_name)
    [WITH FILLFACTOR=x]
    UNIQUE表示唯一索引,可選CLUSTERED、NONCLUSTERED表示聚集索引還是非聚集索引, 可選 FILLFACTOR表示填充因子,指定一個(gè)0到100之間的值,該值指示索引頁填滿的空間所占的百分比
 
 
 SET STATISTICS IO 輸出信息如圖
 
三 創(chuàng)建數(shù)據(jù)測試下上面學(xué)到的理論知識
 
--創(chuàng)建表
CREATE TABLE employee
(
 emp_username varchar (20),
 emp_register DATETIME
)
  
--插入測試數(shù)據(jù)
DECLARE @startid INT
DECLARE @endid INT
SELECT @startid= 1,@endid = 100
WHILE @startid <=@endid
BEGIN
 INSERT INTO employee (
    emp_username,
    emp_register
 ) VALUES (
    /* emp_username - varchar (20) */ '劉'+CAST(@startid AS NVARCHAR(20)),
    /* emp_register - DATETIME */ GETDATE() )
 SELECT @startid =@startid +1;
END
 
-- 查詢employee的執(zhí)行計(jì)劃 和 io  信息
SET STATISTICS IO ON 
SELECT * FROM employee WHERE emp_username = '劉'

 
查看消息輸出的 IO 信息
表'employee'。(1)1掃描計(jì)數(shù)1,(2)邏輯讀取1 次,(3)物理讀取0 次,(4)預(yù)讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預(yù)讀0 次。
輸出的信息和上面的圖片講解的是對應(yīng)的
1.      執(zhí)行的掃描次數(shù) 。
2.      從磁盤讀取的頁數(shù)。
3.      為進(jìn)行查詢而放入緩存的頁數(shù)。
4. 預(yù)讀
T_SQL transaction 語句有很多種的寫法,但是決定那條語句是最優(yōu)的是根據(jù)(logical reads) 邏輯讀取來判斷。
 
 
添加聚集索引 查詢邏輯讀取是否會變少
CREATE CLUSTERED INDEX Idx_emp_username ON employee (emp_username);
 
--然后再執(zhí)行查詢 
SET STATISTICS IO ON
SELECT * FROM employee WHERE emp_username = '劉'

 
查看消息輸出的 IO 信息
表'employee'。掃描計(jì)數(shù)1,邏輯讀取2 次,物理讀取0 次,預(yù)讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預(yù)讀0 次。 
Q 這次邏輯讀取是2次為什么呢 ?
A.難道查詢比表掃描還要慢,答案是對的,數(shù)據(jù)量小的時(shí)候,聚集索引的優(yōu)勢體現(xiàn)不出來。
Q 為什么是2次邏輯讀取
A 現(xiàn)在查詢的時(shí)候如聚集索引圖,先查詢索引頁 ,查找到對應(yīng)的鍵值后,掃描數(shù)據(jù)頁,如果有包含索引,直接在索引頁就可以提取到需要的數(shù)據(jù)。
 
 
上面說了小數(shù)據(jù)量的時(shí)候聚集索引體現(xiàn)不出效果,下面我們繼續(xù)填充數(shù)據(jù)測試 。
 
 
填充測試數(shù)據(jù)到1000
 
表掃描
消息:
表'employee'。掃描計(jì)數(shù)1,邏輯讀取36 次,物理讀取0 次,預(yù)讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預(yù)讀0 次。
 
聚集索引掃描
消息:
表'employee'。掃描計(jì)數(shù)1,邏輯讀取2 次,物理讀取0 次,預(yù)讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預(yù)讀0 次。
 
這個(gè)時(shí)候聚集索引的優(yōu)勢就先顯示出來了 O(∩_∩)O
 
 
 
下面在來講講transaction sql 語句 ,大家在網(wǎng)上看到的一些人說  In like left  不使用索引 ,我們動手來測試下看他們說的對不對 ?
 
 
刪除employee表的索引
DROP INDEX employee.Idx_emp_username
表 'employee'。掃描計(jì)數(shù) 1,邏輯讀取 371 次,物理讀取 0 次,預(yù)讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預(yù)讀 0 次。
打開IO信息
SET STATISTICS IO ON
SELECT * FROM employee WHERE employee.emp_username in ('劉10000')
 

 
消息:
 
 --添加Idx_emp_username聚集索引
CREATE CLUSTERED INDEX Idx_emp_username ON employee (emp_username);
SELECT * FROM employee WHERE employee.emp_username in ('劉10000');

 
消息:
表 'employee'。掃描計(jì)數(shù) 1,邏輯讀取 3 次,物理讀取 0 次,預(yù)讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預(yù)讀 0 次。
 
 使用索引后邏輯讀取3次,沒有使用索引是371次,IN 很好的使用了索引!
 
 下面我們來測試下 LIKE 是否很好的使用索引
 
 刪除索引
 DROP INDEX employee.Idx_emp_username
 打開IO 信息
 SET STATISTICS IO ON
 執(zhí)行查詢
 SELECT * FROM employee WHERE  employee.emp_username like   ('劉1000%')
 
 
 消息:
  表 'employee'。掃描計(jì)數(shù) 1,邏輯讀取 371 次,物理讀取 0 次,預(yù)讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預(yù)讀 0 次。
 
 添加索引
 CREATE CLUSTERED INDEX Idx_emp_username ON employee (emp_username);
 SET STATISTICS IO ON
 SELECT * FROM employee WHERE employee.emp_username  like  ( '劉1000%');
 
 
 
 
表 'employee'。掃描計(jì)數(shù) 1,邏輯讀取 3 次,物理讀取 0 次,預(yù)讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預(yù)讀 0 次。
 
網(wǎng)上很多優(yōu)化的文章寫到查詢不要使用 in like  left ,其實(shí)自己動手測試下看看查詢計(jì)劃就一幕了然了 。

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(1)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)