《資料庫索引設計優化》讀書筆記(五)
阿新 • • 發佈:2019-01-09
第8章 為表連線設計索引
練習
A為父表,B為子表,兩個表做主外來鍵關聯查詢,只有主鍵和外來鍵上有索引,並且A表的主鍵索引和B表的外來鍵索引為聚簇索引。
以A作為外層表做巢狀迴圈連線計算響應時間:
第1步:通過聚簇索引AK訪問A表
索引 AKTR = 1 TS = 10000000
LTR1 * 10ms + 10000000 * 0.01ms = 100s
第2步:通過聚簇索引AK訪問B表
索引 AKTR = 10000000 * 1% = 100000TS = 100000 * 5 = 500000
LTR100000 * 10ms + 100000 * 5 * 0.01ms = 1005s
第3步:提取資料
50000000 * 1% * 0.001% * 0.1ms = 0.5ms
所以以A作為外層表做巢狀迴圈連線響應時間約為1105(100 + 1005)秒
以B作為外層表做巢狀迴圈連線計算響應時間:
第1步:通過聚簇索引AK訪問B表
索引 AKTR = 1 TS = 50000000
LTR1 * 10ms + 50000000 * 0.01ms = 500s
第2步:通過聚簇索引AK訪問A表
索引 AKTR = 50000000 * 0.001% = 500TS = 500
LTR500 * 10ms + 500 * 0.01ms = 5s
第3步:提取資料
50000000 * 1% * 0.001% * 0.1ms = 0.5ms
所以以B作為外層表做巢狀迴圈連線響應時間約為505(500 + 5)秒
8.2 在不新增冗餘欄位的前提下,為該連線設計最佳索引並評估響應時間。
分析:
因為B1 > :B1的FF很小,僅為0.001%,所以可以建立以B1為字首的寬索引(B1,AK,B2)
以B作為外層表做巢狀迴圈連線計算響應時間:
第1步:通過索引B1訪問B表,因為B1是寬索引,所以無需回表訪問
索引 B1TR = 1 TS = 50000000 * 0.001% = 500
LTR1 * 10ms + 500 * 0.01ms = 15ms
第2步:通過聚簇索引AK訪問A表
索引 AKTR = 500TS = 500
LTR500 * 10ms + 500 * 0.01ms = 5005ms
第3步:提取資料
50000000 * 1% * 0.001% * 0.1ms = 0.5ms
所以使用B1上的寬索引(B1,AK,B2), 以B作為外層表做巢狀迴圈連線響應時間約為5((15+5005+0.5)/1000)秒。
根據四個表的記錄數,最佳表訪問順序為C1->CUST->C3->C2
第1步:通過聚簇索引C1PK訪問C1表
LTR1 * 10ms + 1000 * 0.01ms = 0.02s
第2步:通過索引C1PK訪問CUST表
LTR1000 * 10ms + 1000 * 1000 * 0.01ms = 20s -- 平均每個C1PK對應1000行CUST表的記錄
第3步:通過索引C3PK訪問C3表
LTR1000000 * 10ms = 10000s
第4步:通過索引C2PK訪問C2表
LTR1000000 * 10ms = 10000s
第5步:提取資料
1000000 * 0.1ms = 100s
本地響應時間約為 20 + 10000 * 2 + 100 = 20120s
8.4 假設SQL 8.19在一個批任務中會被執行一百萬次。我們需要改進索引麼?調優的空間有多大?有其他方法可以用來提升該SELECT語句的效能嗎?
因為CNO為主鍵聚簇索引,所以SQL 8.19最多返回一行記錄,先計算執行一次的時間
索引 CNOTR = 1 TS = 1
索引 C1PKTR = 1TS = 1
索引 C2PKTR = 1TS = 1
索引 C3PKTR = 1TS = 1
提取資料1 * 0.1ms
LTR4 * 10ms + 4 * 0.01ms + 0.1ms = 40.14ms
一百萬次的執行時間為 1000000 * 40.14ms = 40140s
因為所有的索引訪問都是針對主鍵聚簇索引,所以不需要改進索引。
在CUST表上增加C1TEXT, C2TEXT, C3TEXT三個冗餘列,使用觸發器維護,這樣可以避免表連線,執行時間為:
1000000 * (10ms + 0.01ms + 0.1ms) = 10110s
調優的空間為3/4。
練習
8.1 評估圖8.25中所示連線的響應時間,過濾因子使用給定的值。
A為父表,B為子表,兩個表做主外來鍵關聯查詢,只有主鍵和外來鍵上有索引,並且A表的主鍵索引和B表的外來鍵索引為聚簇索引。
以A作為外層表做巢狀迴圈連線計算響應時間:
第1步:通過聚簇索引AK訪問A表
索引 AKTR = 1 TS = 10000000
LTR1 * 10ms + 10000000 * 0.01ms = 100s
第2步:通過聚簇索引AK訪問B表
索引 AKTR = 10000000 * 1% = 100000TS = 100000 * 5 = 500000
LTR100000 * 10ms + 100000 * 5 * 0.01ms = 1005s
第3步:提取資料
50000000 * 1% * 0.001% * 0.1ms = 0.5ms
所以以A作為外層表做巢狀迴圈連線響應時間約為1105(100 + 1005)秒
以B作為外層表做巢狀迴圈連線計算響應時間:
第1步:通過聚簇索引AK訪問B表
索引 AKTR = 1 TS = 50000000
LTR1 * 10ms + 50000000 * 0.01ms = 500s
第2步:通過聚簇索引AK訪問A表
索引 AKTR = 50000000 * 0.001% = 500TS = 500
LTR500 * 10ms + 500 * 0.01ms = 5s
第3步:提取資料
50000000 * 1% * 0.001% * 0.1ms = 0.5ms
所以以B作為外層表做巢狀迴圈連線響應時間約為505(500 + 5)秒
8.2 在不新增冗餘欄位的前提下,為該連線設計最佳索引並評估響應時間。
分析:
因為B1 > :B1的FF很小,僅為0.001%,所以可以建立以B1為字首的寬索引(B1,AK,B2)
以B作為外層表做巢狀迴圈連線計算響應時間:
第1步:通過索引B1訪問B表,因為B1是寬索引,所以無需回表訪問
索引 B1TR = 1 TS = 50000000 * 0.001% = 500
LTR1 * 10ms + 500 * 0.01ms = 15ms
第2步:通過聚簇索引AK訪問A表
索引 AKTR = 500TS = 500
LTR500 * 10ms + 500 * 0.01ms = 5005ms
第3步:提取資料
50000000 * 1% * 0.001% * 0.1ms = 0.5ms
所以使用B1上的寬索引(B1,AK,B2),
8.3 CUST表中有三個指向程式碼表的外來鍵。評估在巢狀迴圈和最佳表訪問順序下,下述這四表連線的本地響應時間(參見圖8.26)
根據四個表的記錄數,最佳表訪問順序為C1->CUST->C3->C2
第1步:通過聚簇索引C1PK訪問C1表
LTR1 * 10ms + 1000 * 0.01ms = 0.02s
第2步:通過索引C1PK訪問CUST表
LTR1000 * 10ms + 1000 * 1000 * 0.01ms = 20s -- 平均每個C1PK對應1000行CUST表的記錄
第3步:通過索引C3PK訪問C3表
LTR1000000 * 10ms = 10000s
第4步:通過索引C2PK訪問C2表
LTR1000000 * 10ms = 10000s
第5步:提取資料
1000000 * 0.1ms = 100s
本地響應時間約為 20 + 10000 * 2 + 100 = 20120s
8.4 假設SQL 8.19在一個批任務中會被執行一百萬次。我們需要改進索引麼?調優的空間有多大?有其他方法可以用來提升該SELECT語句的效能嗎?
-- SQL 8.19
SELECT CNAME, C1TEXT, C2TEXT, C3TEXT
FROM CUST, C1, C2, C3
WHERE CUST.CNO = :CNO
AND CUST.C1PK = C1.C1PK
AND CUST.C2PK = C2.C2PK
AND CUST.C3PK = C3.C3PK
分析:因為CNO為主鍵聚簇索引,所以SQL 8.19最多返回一行記錄,先計算執行一次的時間
索引 CNOTR = 1 TS = 1
索引 C1PKTR = 1TS = 1
索引 C2PKTR = 1TS = 1
索引 C3PKTR = 1TS = 1
提取資料1 * 0.1ms
LTR4 * 10ms + 4 * 0.01ms + 0.1ms = 40.14ms
一百萬次的執行時間為 1000000 * 40.14ms = 40140s
因為所有的索引訪問都是針對主鍵聚簇索引,所以不需要改進索引。
在CUST表上增加C1TEXT, C2TEXT, C3TEXT三個冗餘列,使用觸發器維護,這樣可以避免表連線,執行時間為:
1000000 * (10ms + 0.01ms + 0.1ms) = 10110s
調優的空間為3/4。