Postgresql管理系列-第七章Heap Only Tuple and Index-Only Scans

本章介紹與索引掃描相關的兩個功能, 即Heap Only Tuple和Index-Only Scans。

7.1. Heap Only Tuple (HOT)

HOT是在8.3版中引入的, 當更新的行存儲在舊行所在的page時,可以有效地使用索引和表的頁。HOT有效的減少了vacuum操作。
源碼目錄README.HOT描述了HOT的細節。 本章簡要介紹了HOT。首先, 7.1.1章節介紹瞭如何在沒有HOT的情況下更新行。接下來,7.1.2部分介紹了HOT是如何執行的。

7.1.1. 更新沒有HOT的行

假設表 “tbl” 有兩列:“id"和"data”;"id"是"tbl"的主鍵。

testdb=# \d tbl
                Table "public.tbl"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 data   | text    |           |          | 
Indexes:
    "tbl_pkey" PRIMARY KEY, btree (id)

表"tbl"有1000個tuples;id爲"1000"的最後一個tuples存儲在表的第5個page。最後一個tuples指向相應的索引元組,其中的鍵爲"1000",其tid爲"(5,1)"。請參閱圖 7.1(a)。

圖7.1. 更新沒有HOT的行
在這裏插入圖片描述

我們考慮如何在沒有HOT的情況下更新最後一個tuples

testdb=# UPDATE tbl SET data = 'B' WHERE id = 1000;

在這種情況下, PostgreSQL不僅會在表page中插入新的tuples, 還會在索引page中插入新的索引tuples。請參閱圖 7.1(b)。
索引tuples的插入會佔用索引頁的空間, 並且索引tuples的插入和vacuum成本都很高。HOT減少了這些問題的影響。

7.1.2. HOT如何執行

HOT行更新的時候,如果更新的行存儲在舊行所在的page時,Postgresql不需要插入相應的index tuples,並且分別設置HEAP_HOT_UPDATED bit和HEAP_ONLY_TUPLE bit爲舊tuples和新tuples的t_informask2,參照圖7.2和7.3

圖 7.2. 更新HOT行
在這裏插入圖片描述

例如, 在這種情況下, “Tuple_1” 和 "Tuple_2"分別設置HEAP_hot_upeded和HEAP_ONLY_TUPLE的bit位。

此外, 無論修剪情況如何,都會使用HEAP_hot_update和HEAP_ONLY_TUPLE bit位執行碎片整理。如下圖所示

圖 7.3. HEAP_HOT_UPDATED和HEAP_ONLY_TUPLE bits
在這裏插入圖片描述

如下, 本文描述了PostgreSQL如何使用HOT更新後的tuples索引掃描訪問更新的tuples。請參閱圖 7.4(a)。

圖 7.4. 修剪行指針
在這裏插入圖片描述

(1) 找出指向目標tuples的索引tuples
(2) 訪問從索引tuples中獲取的行指針 “[1]”
(3) 讀"Tuple_1"
(4) 通過"Tuple_1"的ctid讀"Tuple_2"

在這種情況下, PostgreSQL讀取兩個元組, “Tuple_1” 和 “Tuple_2”, 並通過第5章中描述的併發控制機制來確定哪個是可見的。
但是, 如果刪除表頁中的dead tuples, 則會出現問題。例如, 在圖7.4(a)中, 如果刪除"Tuple_1", 因爲它是dead tuple, 則無法從索引中訪問"Tuple_2"。

爲了解決此問題, 在適當的時候, PostgreSQL將指向舊tuple的行指針重定向到指向新tuple的行指針。在 PostgreSQL中,此處理稱爲修剪。圖 7.4(b)描述了PostgreSQL 在修剪後如何訪問更新的tuples。

(1) 查找index tuple
(2) 訪問從索引tuples中指向的行指針 “[1]”
(3) 通過重定向的行指針訪問指向"Tuple_2"的行指針"[2]"
(4) 從指向point"[2]“的point讀取"Tuple_2”

如果可能發生, 在執行SQL命令 (如 SELECT,UPDATE,INSERT和DELETE) 時,將執行修剪處理。本章沒有介紹確切的執行時間, 因爲它非常複雜。詳細信息。

如果可能, 在修剪過程中,PostgreSQL會在適當的時間刪除dead tuples。在PostgreSQL官方文檔中, 此處理稱爲碎片整理。圖7.5描述了由HOT引發的碎片整理。

圖 7.5. dead tuples碎片整理
在這裏插入圖片描述
請注意, 碎片整理的成本低於正常的VACUM處理成本,因爲碎片整理不涉及刪除索引元組。
因此, 使用HOT可以減少索引也和表頁的消耗;這也減少了VACUUM處理的tuples。因此, HOT對性能有很好的影響, 因爲它最終減少了在update和vacuum的時候index tuples的插入次數。

沒有HOT的示例

爲了清楚地瞭解 HOT的運行情況, 這個示例描述了沒有HOT的情況
當更新後的tuples沒有存儲在old tuples的同一頁中時, 指向該tuple的索引tuple也會插入到索引頁中。請參閱圖 7.6(a)
當索引tuple的鍵值更新時, 將在索引頁中插入新的索引tuple。請參閱圖 7.6(b)

圖7.6.沒有HOT的示例
在這裏插入圖片描述

與HOT相關的統計數據

pg_stat_all_tables爲每個表提供了統計值,也可以查看https://github.com/s-hironobu/pg_stats插件

7.2. Index-Only Scans

爲了降低I/O(輸入/輸出)成本, 當SELECT語句的所有數據都包含在索引鍵中時, 索引掃描(通常稱爲 index-only access)直接使用索引鍵,而不訪問相應的表頁。所有商業RDBMS都提供此項技術 ,如DB2和oracle.Postgresql從9.2版本開始引入。

下面的示例描述Postgresql中index-only scans是如何運行的

假設示例如下:
1.表結構
我們有一個表"tbl",其定義如下所示:

testdb=# \d tbl
      Table "public.tbl"
 Column |  Type   | Modifiers 
--------+---------+-----------
 id     | integer | 
 name   | text    | 
 data   | text    | 
Indexes:
    "tbl_idx" btree (id, name)

2.索引
表"tbl"有一個索引"tbl_idx", 它由兩列組成:“id"和"name”。

3.tuples
“tbl"已經插入了以下tuples
“Tuple_18”,其id爲"18”, 名稱爲"Queen",存儲在第0號頁面中。
“Tuple_19”,其id爲"19", 名稱爲"BOSTON", 存儲在第1號頁面中。

4.可見性
第0號頁中的所有tuples始終可見;第1號頁中的元組並不總是可見。請注意, 每個頁面的可見性存儲在相應的visibility map中, 第6.2節中描述了visibility map.

讓我們探討一下以下select命令執行的時候,Postgresql是如何去取tuples的

testdb=# SELECT id, name FROM tbl WHERE id BETWEEN 18 and 19;
 id |  name   
----+--------
 18 | Queen
 19 | Boston
(2 rows)

查詢從表的兩列獲取數據:“id"和"name”, 索引"tbl_idx"包含這些列。因此,在使用索引掃描時, 乍一看似乎並不需要訪問表頁面,因爲索引tuples包含了必要的數據。然而, 事實上, PostgreSQL原則上必須檢查tuples的可見性,並且索引tuples沒有相關事務的任何信息,例如,heap tuples的t_xmin和t_xmax, 在第5.2節中所述。因此, PostgreSQL必須訪問表數據, 以檢查索引tuples中數據的可見性。這就像把馬車放在馬面前。

爲了避免這種尷尬,PostgreSQL使用表的visibility map。如果存儲在一個頁面中的所有tuples都可見, PostgreSQL將使用索引tuples的鍵, 並且不訪問從索引tuples指向的表頁來檢查其可見性;除此之外,PostgreSQL會讀取索引tuples指向的表tuples,並檢查tuples的可見性,這是一般常見的過程。

在此示例中, 不需要訪問"Tuple_18", 因爲存儲"Tuple_18"的第0頁是可見的, 也就是說,在第0頁中包括Tuple_18的所有tuples都可見。相反, 需要訪問"Tuple_19" 來處理併發控制,因爲第1頁的可見性是不可見。參見圖7.7。

圖7.7. Index-Only Scans如何執行
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章