二叉樹搜尋具有對數時間的表現有個假設:輸入資料具有相當的隨機性。現在我們看雜湊表,這種資料結構,其在插入、刪除、查詢操作上也具有常數評價時間的表現,而且這種表現以統計為基礎,不依賴資料的隨機性。
我們先看看pg裡的雜湊函式,再看pg裡動態雜湊表「dynmaic hashtable」(我認為用
「可擴充套件雜湊表」更能體現「dynmaichashtable」的功能,更貼近中國人用詞習慣,以後就用「可擴充套件雜湊表」吧。)結構、雜湊表上的操作(增刪查改)以及可擴充套件。
說雜湊函式前先澄清一下 碰撞,碰撞根據使用的場合不同有兩種情況,一是雜湊函式在把普通值打散/計算出雜湊值時可能產生的碰撞,這個需要由雜湊函式本身解決,王小雲教授研究的碰撞就是這個碰撞;另乙個是雜湊表中根據雜湊鍵值安排雜湊鍵所在位置時的碰撞,解決這種碰撞的方法有一次探測(linear probing)、二次探測(quadratic probing)、開鏈(separate chainning)等多種解決方法,pg以開鏈解決這個碰撞問題。
hash函式:
pg在hash.h中有下列hash函式
extern datum hashchar(pg_function_args);
extern datum hashint2(pg_function_args);
extern datum hashint4(pg_function_args);
extern datum hashint8(pg_function_args);
extern datum hashoid(pg_function_args);
extern datumhashenum(pg_function_args);
extern datum hashfloat4(pg_function_args);
extern datumhashfloat8(pg_function_args);
extern datumhashoidvector(pg_function_args);
extern datumhashint2vector(pg_function_args);
extern datumhashname(pg_function_args);
extern datumhashtext(pg_function_args);
extern datumhashvarlena(pg_function_args);
extern datumhash_any(register const unsigned char *k, register int keylen);
extern datumhash_uint32(uint32 k);
下面這些雜湊函式做將原值做一些位與或轉換後,將結果作為引數呼叫hash_uint32繼續雜湊運算
hashchar()、hashint2()、hashint4()、hashint8()、hashoid()、hashenum()
下面這些雜湊函式做將原值做一些位與或轉換或型別轉換後,將結果作為引數呼叫hash_any繼續雜湊運算
hashfloat4()、hashfloat8()、hashoidvector()、hashint2vector()、hashname()、hashtext()、hashvarlena()
這麼多的雜湊函式最終落到了hash_uint32和hash_any這兩個雜湊函式上,加上兩個做雜湊的巨集mix(a,b,c)和final(a,b,c)完成了雜湊運算。hash_uint32(uint32 k)像hash_any(&k, sizeof(uint32))一樣有著同樣的結果,但hash_uint32更快,並且不強制呼叫者把k儲存在記憶體中。
關於雜湊函式研究,可以推薦兩個人的書/文章看看,乙個是中科院的裴定一教授,可以看他的書和文章。有優於pki的cpk標識認證專利的南湘浩教授需要雜湊函式的時候就是向裴定一教授要的。南湘浩和曲延文教授以及孫玉院士(都是大牛)合作成立了qns工作室,我第一次路過工作室時,第一反映是這是個皮包公司,因為在租金不菲的中關村軟體園裡有偌大面積,但又沒有幾個工作人員,後來登門拜訪受教才了解內情。另乙個是bob jenkins,可以到他的** 看。或者看他們的**。
可擴充套件雜湊表可以無限增長。可擴充套件雜湊表有乙個頂層的「目錄」,他的每乙個入口指向ssize個雜湊桶的段的頭部,最大雜湊桶數是dsize * ssize,dsize是可以增大的。當然,雜湊表裡的記錄數可以更大,但是我們不想要乙個雜湊桶裡有很多記錄或效能降是低。在共享記憶體中分配的雜湊表時,因為他的位址是固定的,「目錄」不能增大。目錄的大小應該用hash_select_dirsize選擇。非共享雜湊表的目錄初始化大小可以是預設的。
可擴充套件雜湊表和幾個資料結構有關,乙個是hctl,這個是建立可擴充套件雜湊表時的資訊表,乙個是htab,這個就是雜湊表結構,乙個是hashhdr,這個是雜湊表頭結構,包含了雜湊表的所有可變資訊,還有hashsegment、hashbucket、hashelement等結構,乙個hashsegment是hashbucket陣列的頭,乙個hashbucket是hashelement鍊錶。結構定義見下面。這些結構和起來組成了可擴充套件雜湊表。根據pg預設引數建立的可擴充套件雜湊表結構圖在下面。
typedef struct hashctl
hashctl;
struct htab ;
struct hashhdr ;
typedef hashelement *hashbucket;
typedef hashbucket *hashsegment;
根據pg預設值建立的可擴充套件雜湊表結構圖如下:
雜湊表結構圖
建立過程涉及函式及功能:
根據info資訊和給定名字及hashelement元素個數進行計算建立可擴充套件雜湊表
htab * hash_create(const char *tabname, long nelem, hashctl*info, int flags)
分配相應數目(dsize)的hashsegment陣列
static bool init_htab(htab *hashp, long nelem)
計算給定數的以2為底加1取正對數值
int my_log2(long num)
給雜湊表的hashsegment分配相應個數(ssize)的hashbucket
static hashsegment seg_alloc(htab *hashp)
根據entry大小計算要分的hashelement的個數
static int choose_nelem_alloc(size entrysize)
分配hashelement+entry並加入到hashhdr的freelist鍊錶
static bool element_alloc(htab *hashp, int nelem)
雜湊表的銷毀:
主要是呼叫memorycontextdelete(hashp->hcxt)(參見《pg記憶體管理機制三》)銷毀雜湊表
void hash_destroy(htab*hashp)
建立流程圖如下:
建立可擴充套件雜湊表流程圖
上圖中紅色框主要是根據條件設定htab結構型別變數的各成員,右邊黃色框中主要是計算hashsegment、hashbucket以及hashelement成員的數目並為它們分配記憶體。
就到這兒吧。
postgresql中的資料分割槽
目錄 環境文件用途 詳細資訊 環境系統平台 n a 版本 10.0,9.6,8.4 文件用途 本文旨在用於指導資料分割槽和資料分割槽方法。詳細資訊 什麼是資料分割槽?對於具有極大表的資料庫,分割槽對於資料庫設計人員而言是一種慣用的技巧,可以提高資料庫效能並使維護更加容易。postgresql資料庫中...
Kafka在zookeeper中的資料結構
一 brokers節點 brokers brokers topics brokers topics test2 brokers topics test2 partitions brokers topics test2 partitions 0 brokers topics test2 partiti...
clickhouse insert的資料結構
clickhouse insert大致分為兩部分 1.sql語句部分 insert into table f1,f2 2.資料部分資料部分又分為3部分 頭,資料,尾 資料頭 資料塊1 資料塊2 資料塊n 資料尾從中可以看出 每個insert可以包含多個資料塊,每個資料塊可以包含多行。乙個完整的ins...