postgresql之ctid的淺談


   ctid: 表示數據記錄的物理行當信息,指的是 一條記錄位於哪個數據塊的哪個位移上面。 跟oracle中偽列 rowid 的意義一樣的;只是形式不一樣。
   例如這有個一表test;查看每行記錄的ctid情況
mydb=> select ctid,* from test;
 ctid  |  id  |  name  
-------+------+--------
 (0,1) | 1001 | lottu
 (0,2) | 1002 | rax
 (0,3) | 1003 | xuan
 (0,4) | 1004 | li0924
 (0,5) | 1001 | ak
    格式(blockid,itemid):拿其中(0,1)來說;0表示塊id;1表示在這塊第一條記錄。
 
  1. 去重:  我們知道rowid在oracle有個重要的作用;被用作表記錄去重;同理 ctid在postgresql里面同樣可以使用。例如test表id為1001有兩條記錄;現在演示下;
mydb=> delete from test where ctid not in (select min(ctid) from test group by id);
DELETE 1
mydb=> select ctid,* from test;
 ctid  |  id  |  name  
-------+------+--------
 (0,1) | 1001 | lottu
 (0,2) | 1002 | rax
 (0,3) | 1003 | xuan
 (0,4) | 1004 | li0924
(4 rows)

剛剛我們刪除了(0,5)這條記錄; 現在我們把這條記錄插入下;看下;

mydb=> insert into test values (1001,'ak');
INSERT 0 1
mydb=> select ctid,* from test;
 ctid  |  id  |  name  
-------+------+--------
 (0,1) | 1001 | lottu
 (0,2) | 1002 | rax
 (0,3) | 1003 | xuan
 (0,4) | 1004 | li0924
 (0,6) | 1001 | ak
(5 rows)

奇怪了;為什么不是(0,5),而是(0,6)這個跟postgresql多版本事務有關;跟偽列cmin,cmax有關;跟本文講的ctid沒點關系;這是postgresql的特性;也就是這樣;postgresql里面沒有回滾段的概念;那怎么把(0,5)在顯示呢;想這塊(0,5)的空間再存放數據;postgresql里面有AUTOVACUUM進程;當然我們也可以手動回收這段空間;

mydb=> delete from test where name = 'ak';
DELETE 1
mydb=> vacuum test;          
VACUUM
mydb=> insert into test values (1001,'ak');
INSERT 0 1
mydb=> select ctid,* from test;
 ctid  |  id  |  name  
-------+------+--------
 (0,1) | 1001 | lottu
 (0,2) | 1002 | rax
 (0,3) | 1003 | xuan
 (0,4) | 1004 | li0924
 (0,5) | 1001 | ak
(5 rows)

2. 我們剛剛說道 0表示塊id; test數據太少了;不好解釋;新建一個表test2

mydb=> drop table test2;
DROP TABLE
mydb=> create table test2 (id int primary key, name varchar(10));
CREATE TABLE
mydb=> insert into test2 select generate_series(1,1000),'lottu' || generate_series(1,1000);
INSERT 0 1000

 我們看下id=1000的ctid的blockid是多少;答案是5;意思是說該表的記錄記錄到第6個塊;(因為是從0開始的)

mydb=> select ctid,* from test2 where id = 1000;
  ctid  |  id  |   name    
--------+------+-----------
 (5,75) | 1000 | lottu1000
(1 row)
當然這樣查表記錄占了幾個block;假如我這是隨機插入的;那id=1000;就不一定是在第6塊;
我們可以借助系統視圖pg_class;其中relpages,reltuples分別代表塊數,記錄數!
mydb=> analyze test2;
ANALYZE
mydb=> select relpages,reltuples from pg_class where relname = 'test2';
 relpages | reltuples 
----------+-----------
        6 |      1000
(1 row)
總結: ctid存在的意義:表示數據記錄的物理行當信息,指的是 一條記錄位於哪個數據塊的哪個位移上面。 跟oracle中偽列 rowid 的意義一樣的;只是形式不一樣。
vacuum: 回收未顯示的物理位置;標明可以繼續使用。
generate_series: 為一個序列函數;例如1-100;就是generate_series(1,100);0-100直接的偶數generate_series(0,100,2)
                          其中的0表示序列開始位置;100代表結束位置;2為偏移量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM