国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數據庫技術|

服務器之家 - 數據庫 - Sql Server - SQL Server索引結構的具體使用

SQL Server索引結構的具體使用

2022-02-25 17:23喬安生 Sql Server

索引是數據庫的基礎,只有先搞明白索引的結構,才能搞明白索引運行的邏輯,本文主要介紹了SQL Server 索引結構的具體使用,具有一定的參考價值,感興趣的可以了解一下

索引是數據庫的基礎,只有先搞明白索引的結構,才能搞明白索引運行的邏輯

本文通過 索引表、數據頁、執行計劃、IO統計、B+Tree 來盡可能的介紹 SQL 語句中 WHERE 部分,和 SELECT 部分 的運行邏輯

 

名詞介紹

B+Tree:一種數據結構

  • 數據頁:數據庫保存數據的最小單位。(SQL Server一個數據頁的大小是 8K,一個表中所有的數據都被保存到一個個的數據頁中)
  • 索引組織表:大白話一張表有聚集索引就是索引組織表(把表中的數據頁以 B+Tree 的方式組織起來)
  • 索引表:一個索引對應一張索引表,索引表中每條數據都對應一張數據頁。

通過DBCC IND(數據庫, 表名, 索引Id) 命令可以獲取到表中指定索引的索引表信息

通過DBCC PAGE(數據庫, 1, 數據頁Id, 3) 命令可以獲取到某個數據頁中的數據

B+Tree結構

SQL Server索引結構的具體使用

準備數據

DROP TABLE Org_User
-- 創建測試表
CREATE TABLE Org_User(Id INT,UserName NVARCHAR(50),Age INT)
-- 創建聚集索引和非聚集索引
CREATE CLUSTERED INDEX Org_User_Id ON Org_User(Id)
CREATE NONCLUSTERED INDEX Org_User_Name ON Org_User(UserName)

CREATE TABLE #Temp(Id INT)
INSERT INTO #Temp VALUES(1)
INSERT INTO #Temp VALUES(2)
INSERT INTO #Temp VALUES(3)
INSERT INTO #Temp VALUES(4)
INSERT INTO #Temp VALUES(5)
INSERT INTO #Temp VALUES(6)
INSERT INTO #Temp VALUES(7)
INSERT INTO #Temp VALUES(8)
INSERT INTO #Temp VALUES(9)
INSERT INTO #Temp VALUES(10)

-- 批量插入10W條數據
INSERT  INTO dbo.Org_User
SELECT T1.Id, "UserName_" + CONVERT(NVARCHAR(20), T1.Id) AS "UserName", T1.Id + 10 AS "Age" FROM 
(
    SELECT TOP 100000 Id = ROW_NUMBER() OVER (ORDER BY T1.Id)
    FROM #Temp AS T1
    CROSS JOIN #Temp AS T2
    CROSS JOIN #Temp AS T3
    CROSS JOIN #Temp AS T4
    CROSS JOIN #Temp AS T5
    ORDER BY T1.Id
) AS T1

SQL Server索引結構的具體使用

SELECT name, index_id,type_desc FROM SYS.INDEXES WHERE object_id = OBJECT_ID("Org_User");

SELECT  index_id ,
        index_type_desc ,
        index_depth ,
        page_count
FROM    sys.dm_db_index_physical_stats(DB_ID("Core2022"), OBJECT_ID("Org_User"), NULL, NULL, NULL)

SQL Server索引結構的具體使用

在 sys.dm_db_index_physical_stats 這張系統表中

index_depth 表示索引的深度 (對應上圖B+Tree就是樹的高度)

page_cout 表示索引數據頁的數量 (對應上圖B+Tree就是葉子節點的數量)

這里獲取索引信息主要是為了 index_id

 

索引表

DBCC IND(Core2022, Org_User, 1)

SQL Server索引結構的具體使用

DROP TABLE dbcc_ind
-- 創建一張表用來保存索引表信息
CREATE TABLE dbcc_ind
(
    PageFID NUMERIC(20),
    PagePID NUMERIC(20),
    IAMFID NUMERIC(20),
    IAMPID NUMERIC(20),
    ObjectID NUMERIC(20),
    IndexID NUMERIC(20),
    PartitionNumber NUMERIC(20),
    PartitionID NUMERIC(20),
    iam_chain_type VARCHAR(100),
    PageType NUMERIC(20),
    IndexLevel NUMERIC(20),
    NextPageFID NUMERIC(20),
    NextPagePID NUMERIC(20),
    PrevPageFID NUMERIC(20),
    PrevPagePID NUMERIC(20)
)

--DROP PROC proc_dbcc_ind
-- 創建存儲過程
CREATE PROC proc_dbcc_ind
AS
DBCC IND(Core2022,Org_User,1)

-- 把索引表中的數據批量插入到 dbcc_ind 中
INSERT INTO dbcc_ind
EXEC proc_dbcc_ind
SELECT 
    PagePID, -- 改行數據對應的數據頁
    IndexLevel, -- 表示改行數據的級別 0葉子節點,1分支節點,=2根節點,僅限該Demo
    NextPagePID, -- 當前節點的后繼節點 (后面的那個數據頁)
    PrevPagePID -- 當前節點的前驅節點 (前面的那個數據頁)
FROM dbcc_ind
SELECT 
    PagePID,
    IndexLevel,
    NextPagePID,
    PrevPagePID 
FROM dbcc_ind 
WHERE IndexLevel = 0
ORDER BY NextPagePID

SQL Server索引結構的具體使用

對 DBCC IND 中的數據進行一個總結

通過觀察葉子節點的數據可以得到,每個節點都有一個前驅指針和后繼指針,構成了一個雙向鏈表

通過 IndexLevel 這個字段區分 根節點、分支節點、葉子節點

通過 NextPagePID 和 PrevPagePID 兩個字段把相同深度的節點構成了一個雙向鏈表

 

數據頁

DBCC TRACEON(3604) — 打開跟蹤標記,不打開的話 DBCC PAGE 只能查看分支節點中的數據,不能查看葉子節點中的數據

根節點

SQL Server索引結構的具體使用

分支節點

SQL Server索引結構的具體使用

葉子節點

SQL Server索引結構的具體使用

非聚集索引的葉子節點

SQL Server索引結構的具體使用

對索引表和根節點對應的數據頁,分支節點對應的數據頁,葉子節點對應的數據頁進行總結

聚集索引

  葉子節點中保存的是 Org_User 表中的數據

  根節點和分支節點中保存的是指向下一級節點的條件

  索引表中同級的節點都有一個前驅和后繼指針,這兩個指針把同級的節點構建成了一個雙向鏈表

非聚集索引

  根節點和分支節點與聚集索引一直,都是指向下一級節點的條件

  葉子節點有區別包含 創建非聚集索引是指定的Key、指向該行數據實際地址的Key、保證索引唯一的Key

    UserName 就是創建索引時指定的,如果創建時指定多個,這里也會有多個

    Id 這個是指向這行數據真實地址的指針表結構不同這個Key也不一樣

      索引組織表:這個Key就是創建聚集索引時指定的 Key

      堆表:就值這個行數據所在堆表的地址

    UNIQUIFIER 如果創建索引時指定該索引時唯一索引,那么這里就不會有這個字段,否則就會有這個字段用來區分重復的數據

通過索引表,找到 Id = 66666 的這行數據所在的數據頁    

SQL Server索引結構的具體使用

對上圖進行解釋

拿著 66666 從根節點指向的數據頁開始找

66666 > 36017 所以就跳轉到 491 這個數據頁

66511 < 66666 ≤ 66669 所以就跳轉到 2755 這個數據頁

因為 2755 這個數據頁已經是葉子節點了,直接在里面搜索 66666

就找到了這一行數據

SET STATISTICS IO ON 
SELECT * FROM Org_User WHERE Id = 66666

SQL Server索引結構的具體使用

回表

SQL Server索引結構的具體使用

因為這條SQL返回的字段是 Select *

非聚集索引里面沒有 Age 這個字段

因此根據 UserName_66666 從非聚集索引中找到這條數據之后,根據 Id 到聚集索引里面在查一次,找到 Age 這個字段

SQL Server索引結構的具體使用

覆蓋索引

SQL Server索引結構的具體使用

Select Id,UserName 非聚集索引里面這兩個字段都有,所以就沒有必要在查詢聚集索引了

舉一個例子

SET STATISTICS IO ON
SELECT * FROM [Org_User] WHERE Id >= 1 AND Id <= 10
SELECT * FROM [Org_User] WHERE Id IN (1,2,3,4,5,6,7,8,9,10)

-- 上面這兩個SQL只有在 Id 為 Int 類型的時候才等價,在等價的前提下
-- 第一個SQL的效率要遠超于第二個SQL

/*
SET STATISTICS IO ON (開啟后輸出的內容)
(10 行受影響)
表 "Org_User"。掃描計數 1,邏輯讀取 3 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。

(10 行受影響)
表 "Org_User"。掃描計數 10,邏輯讀取 30 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。

很明顯 第一個SQL只有3次邏輯讀,而第二個有30次邏輯讀

*/

只有搞明白了索引運行的邏輯,結合執行計劃等工具,才能搞明白什么情況下那些SQL更好

謠言:

  COUNT(*) 和 COUNT(列) 誰快,誰慢

  首先這兩種寫法都不等價 COUNT(*) 是所有的數據 COUNT(列) NULL值不參與運算,所以如果COUNT的某一列中包含了NULL值算出來的數據可能就有問題了

  查詢速度

    COUNT(*) 更塊

    COUNT(列) 會受偏移量和字段中數據的大小影響

      (通過 SET STATISTICS TIME ON 可以非常簡單的得出結論)

  SQL語句 大表寫前面,小表寫后面

    當前數據庫都會對SQL進行優化,所以無所謂誰在前,誰在后

  IN 與 EXISTS 誰好誰壞

    當前數據庫都會對SQL進行優化,所以無所謂誰好,誰壞

  這些坑人的謠言還有很多,有些在老版本的數據庫是對的,在當前的數據庫中已經過時了。

到此這篇關于SQL Server索引結構的具體使用的文章就介紹到這了,更多相關SQL Server 索引結構內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文地址:https://www.cnblogs.com/ansheng/p/15931359.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美一区永久视频免费观看 | 可以免费在线观看av的网站 | 国产高清视频一区二区 | 日韩精品久久久久 | 免费看黄色一级大片 | 精品国产欧美一区二区三区成人 | 日韩中文视频 | 亚洲综合色视频在线观看 | 日韩精品视频在线 | 九色 在线 | 久久综合888 | 欧美国产日韩一区 | 欧洲一区二区三区 | 成人免费黄色毛片 | 国产人成精品一区二区三 | 欧美一级在线观看 | 日韩精品一区二区三区视频播放 | 这里有精品视频 | 中文字幕在线一区 | 亚洲精品视频免费在线观看 | 亚洲视频精品在线 | 成人一区二区三区在线观看 | 成人aaa视频 | 亚洲国产成人久久 | 欧美成人久久久免费播放 | 青青草超碰在线 | 精品国产乱码久久久久久1区2区 | 久久se精品一区精品二区 | 欧美一区二区在线视频 | 亚洲人成网站在e线播放 | 亚洲精品午夜视频 | 日韩国产一区二区 | 中文字幕在线影院 | 欧美日韩第一页 | 精品国产一区三区 | 久久精品中文 | 色五月激情综合网 | 日韩成人在线看 | 视频一区中文字幕 | 伊人五月天在线 | 91午夜伦伦电影理论片 |