COMP9315 week07課堂筆記

Signature-based Selection

在這裏插入圖片描述
Descriptor 也叫signature。
從individual attributes裏提取併合並信息去組成單個bitstream,捕獲tuple的內容。
signature存儲在signature file中。每個tuple都有自己的signature。
在這裏插入圖片描述
但signature不會決定record的位置。signature file比data file 更小。

在這裏插入圖片描述
一個signature從一個tuple中“總結”數據。
(codeword是)tuple的每個attribute用m bit長的bitstream,其中k bits設爲1。
tuple descriptor(signature)是指把codewords結合起來,比如通過overlaying方式結合(bitwise-OR)。目的是大約一半的bits被置爲1。

創建對於attribute A 的k-in-m codeword

//m is length of codeword,k is the number of bits we set to 1
bits codeword(char *attr_value, int m, int k)
{
	int nbits=0; //count of set bits
	bits cword =0;
	srandom(hash(attr_value));
	while (nbits < k){
		//generate random bit positions 0 to m-1
		int i = random() % m;
		// if cword does not have this set bit 
		if (((1 << i) & cword)	== 0) {
		// i<<i--> ith position in 32 bits is 1, and it does bitwise "OR" into codeword.
			cword |= (1 << i);
			nbits++;
		}
	}
	return cword; // m-bits with k 1-bits and m-k 0-bits
}

以上程序將隨機的bit position置爲1,直到其中k個bits被置爲1.
在這裏插入圖片描述
對於每個attribute,我們根據他的值生成codeword。並把這些codewords “or”在一起,獲得signature。

bits desc=0
for (i=1li<=n;i++){
	bits cw = codeword(A[i])
	desc = desc | cw
}

一個tuple descriptor,是一個長n bits,並且有一部分被置爲1的 bit-string。
tuple descriptor的目的是近一半的bits置爲1,但有時因爲有codewords上bit position是重疊的,所以可能會小於1半。所以只有當每個codeword上bit position不同時,纔會達到nk個bits置爲1。
在這裏插入圖片描述
data file存儲所有的tuples,parallel file存儲tuples的signature。

SIMC Queries

在這裏插入圖片描述
對於query q in SIMC:
1.首先我們創建一個query descriptor desc(q)。例子的query是pmr。
2. 對於已知attribute,我們可以創建它的codeword。對於未知的,我們將其codeword的設爲0。然後將所有已知codeword“or”在一起得到desc(q)。
3.我們將desc(q)與tuple descriptor file中每個descriptor比較。我們想找到tuple descriptor 與desc(q)相匹配的那些tuples。
4.對於匹配成功的tuples,我要知道它們屬於哪些pages,並將這些pages的pageID合併入一個列表,之後進行check pages。
5. 循環list,取得每個Page,scan每個page並檢查所有的tuples是否匹配query的attributes,是的話就加入到answer set 裏。
(matches(D[I],desc(q))—>tuple descriptor的bits對應了tuple裏的所有attributes,如果這個tuple descriptor的attribute對應的bits set與query descriptor相同,說明tuple descriptor的這個attribute與query descriptor中的attributes相同。)
6. 我們通過檢查query descriptor 的bits是否是tuple descriptor的子集(通過bitwise “and”),知道是否query descriptor 中attribute的值與tuple descriptor相同。

PageTocheck = {}
for each descriptor D[i] in signature file {
	if (matches(D[i],desc(q))) {
		pid = pageOf(tupleID(i))
		pageToCheck = pagesToCheck U pid
	}
}
for each pid in pagesToCheck{
	Buf = getPage(dataFile,pid)
	check tuples in Buf for answers
}
//where ...
#define matches(rdesc,qdesc)
				((rdesc & qdesc)==qdesc)

在這裏插入圖片描述
如上圖所示,Clearview那行tuple不包含Perryridge,但由於codewords疊加仍然匹配。所以我們需要再check一次。我們把這種種錯誤匹配叫做false match。
爲了避免太多false match,我們要儘可能讓tuple descriptor和query descriptor大,並且不會有太多的置爲1的bits 出現在codewords中。

在這裏插入圖片描述
False match probability:false match佔總tuple的比例。
除了上面這種情況,還有一種就是不同的attribute具有相同的codeword也會導致False match。---->也叫哈希碰撞(hash collision)。
這種情況下,我們要對不同的attribute使用不同的hash函數。

減少False match probability的方法:
1.對不同的attribute使用不同hash function。
2.增加descriptor的size(m)
3.k值的選擇–>儘量使每個signature一半的bits被置爲1。

大的descriptor的size意味着要讀更多的descriptor data。
K值過大---->則對於每一個tuple,signature裏的幾乎所有bits被置爲一,增加overlapping的概率。
K值過小-----則沒有足夠的bit set去區分每個attribute的值, 增加collisions的概率。

在這裏插入圖片描述
獲得優化m和k的方式:
1.開始的時候選擇一個合適的false match probability,e.g. pF<10^(-5)。
2.基於公示生成m和k:
k = 1/ln2 * ln(1/pF)
m=(1/ln2)^2 * n * ln(1/pF)

在這裏插入圖片描述
pmr query的Cost:
Costpmr = bD(讀所有tuple descriptors的代價) + bq (讀取所有成功匹配的tuples的代價)

r是signature的個數,一個tuple包含1個signature,cD(capacity of Descriptors for each page)是一頁有多少signature。m是一個signature裏有多少bits。B是page的size。
cD = floor(B/ceil/(m/8))
bD = ceil(r/cD)。

rq是真正匹配的tuple數量,rF是false matches的數量。
Expected false matches = rF = (r-rq)pF ≅ rpF if rq<<r(通常情況下pmr的rq比較小)
e.g. 最壞情況的bq=rq+rF(rq和rF都在不同的pages),最好情況的bq=1(都在同一個pages),平均情況bq = ceil(b(rq+rF)/r)

在這裏插入圖片描述
設 90%的false match 與true match在同一頁,
10%的false match 與true match不在同一頁。

data page的頁數:
b=ceil(r/c)=ceil(102400/100)=1024.
signature data的頁數:
signatures per page = c_D = floor(B/bytes(m))=floor(8192/8)=1024
total signature pages = b_D = ceil(r/c_D) = ceil(102400/1024)=100

需要讀的data pages 的數量:
true match pages = b_q = 100

false match records = r_F = (r-r_q)*p_F = (102400(因爲一個tuple有一個signature)-1000) * 0.01 = (大約) 100

90 false matches occur as part of b_q

10 false matches occur one-per-page, 所以 b_F = 10

Total pages read:
#pages = signature pages + true match pages(也包括了90%的false match,所以無需再讀) + false match pages = 100 +100 + 10 = 210

如果用linear scan,則需讀 1000 pages。
如果用multi-attributed hashing,有7個未知的bits,則我們需讀2^7=128 pages。但如果有8個未知的bits,則需要讀2 ^8=256 pages。

但可不可以更好?

Page-level SIMC

在這裏插入圖片描述
上面是每個tuple有一個signature,但我們可以每個page有一個signature。
c是每個page的tuples的數量。
我們可以想象成一個page相當於c*n個attributes 的大tuple。
所以page descriptor 比 tuple descriptor 大很多。
E.g. n=4, c=64, pF=0.001,所以page signature m約等於3680 bits,也就是460bytes。
通常情況下,pages 是1~8KB,也就是8~64 PD/page(cPD)
比如,如果每個signature 有 460 bytes,一個page是8192 bits=8K,則一個page有17個PD。
在這裏插入圖片描述
Query descriptor也需要檢查每個PD是否是他的子集,如果是的話去讀取它們。

pmr query using page descriptor:

pageTocheck = {}
for each descriptor D[i] in signature file{
	if (matches(D[i],desc(q))){
		// directly get Page ID
		pid =i
		pagesToCheck = pagesToCheck U pid
	}
}
//Generate set of pages to check
for each pid in pagesToCheck {
	Buf = getPage(dataFile,pid)
	check tuples in Buf for answers
}

在這裏插入圖片描述
與之前tuple-level差不多,但不同點是:
#pages = signature pages + true match pages +
false march pages = 64+100+1 = 165.—>讀的比原來少很多,因爲signature比原來少,且false match 作用在page上而不是tuple。

但還可以做的更好。

Bit-sliced SIMC

在這裏插入圖片描述
Page-level signature總共b個,長m bites。而Bit-sliced signature將Page-level signature切成了共m個,每個長b bits。

但它存在問題是,改進後Bit-sliced signature的長度變成了data file的頁數,如果想要加更多頁,signature的長度就要變長。但因爲它們是一個緊接下一個存儲在descriptor file的,改變長度很難。

我們找到query descriptor中的“1”以及對應bit slice ,對它們進行“and”操作。結果中的“1”,對應了包含了所有query中的“1”的那些頁。

//we assume every page is going to match
matches = ~0 // all ones
//scan through query descriptor, looking for each bit in position i which set to 1
for each bit i set to 1 in desc(q){
	//fetch bits slide i and add it into matching bit string
	slice = fetch bit-slice i 
	matches = matches & slice
	//above moves eliminate some of pages that do not have a "1" in that particular bit position.  
}
// Above loops matches a bit string where there are "1" bit for each page that contains potentially matching tuples.
// As below, we simply iterate through the matches bit string for each bit which is set to 1. Then, we scan those page for matching records.
for each bit i set to 1 in matches {
	fetch page i
	scan page for matching records
}

以上算法很有效率,因爲desc (q) 有小於長度一半的’1’。
假設我們的query descriptor有k bit,但只有一個‘1’,我們只需要讀 K bit slices就可以了。
在這裏插入圖片描述
#pages = signature pages + true match pages +
false march pages = 10+100+10 = 121

如果bit slices也要存在pages裏,所以如果我們將多個bit slices存在一個buffer page裏,則會減少讀的頁數。

注意這裏的false match pages與tuple-level 相同。所以對於bit-slice和tuple-level我們可以用相同的matching pages。

因爲signature pages和false march pages都是間接成本,且這裏較小,所以此方法的間接成本最小。

這裏不用擔心基於不同query每個attribute分配多少bits,因爲對於不同的query,每個attribute貢獻的bits相同。在此方法下,query擁有的attributes越多,則query中‘1’越多,需要讀的bit slices也越多。這也可能產生更多的cost。所以query的不同,cost也會隨之改變。

Assignment 2

在這裏插入圖片描述
R.info: relation的信息,比如table裏有多少tuples,tuple signature佔多少pages,一共多少pages…
R.data: 包含tuples的data file。attribute類型是string。
R.tsig: 包含tuple signatures的file。
R.psig:包含page-level signatures的file。
R.bsig:包含bit-slice signatures的file。在這裏插入圖片描述
tupSize = #attributes
signature 長m bits,大約ceil(m/8) bytes
在這裏插入圖片描述
在Data file的每一頁的開始記錄了當前頁tuple個數。Signature Page也如此。
在這裏插入圖片描述
gendata:用於生成tuple的命令。
stats:獲取關於relation的信息,用於debug的命令。
dump:打印所有的tuples的命令。
ADT是我們要創建的命令。

create在這裏插入圖片描述

注意命令裏需要給的是PF的倒數。
create創建了一個新的relation,以及data file,info file和3個signatures。
#attrs決定了tuple的size。
#tuples決定了b,也就是length of bit-slices。
用pF取決定signature的m和k。
創建files RelName.info, RelName.Data…
開始的時候data和signnature是空的。
當完成代碼時,RelName.bsig中的bit-slices的bits全是0。RelName.psig也如此。

老師執行順序:
ls—> make---->lf create---->./create R 10000 5 1000
—>lf R.* (linux中lf命令=ls-l)----->./stats R----->./gendata ([startID]默認是6個0加1百萬個1,[seed]默認是0)---->./gendata 10 5 —>./stats R---->(慎用rm -f R. * )---->./create R 10000 5 1000—>./stats R---->./gendata 10 5 ---->./gendata 10 5 | ./insert R—>./select R ‘?,?,?,?,a5-001’ x---->./gendata 9990 5 1000010 | ./insert R---->./stats R----->./select R ‘1000001,?,?,?,?’(因爲未indexing,所以要全部讀)----->./select R ‘1010000,?,?,?,?’—>./select R ‘?,?,a3-101,?,?’ x | tail -6 只會返回query stats。

gendata

在這裏插入圖片描述
只有第一個attribute是唯一的。 後三個attribute的值隨着特定值循環,所以不唯一。

insert

在這裏插入圖片描述
-v決定insert進哪一頁

select

在這裏插入圖片描述
不加‘?’ 因爲shell可能對它敏感。
pmr是取交集。

Select實現方法

//Build query
q = startQuery(r, qstr, type):
	check for valid query(e.g. #tuples)//e.g. not enough #attributes
	//t for tuple, p for page, b for bit-sliced,x for no signature
 	T = type of signature (t,p,b,x)
	Sig = build query signature of type T
	use Sig to determine list of interesting pages
	q->pages = bit-string of interesting pages
if (q==NULL) fatal error
//Scan & Display function
scanAndDisplayMatchingTuples(Query q):
	foreach PID in q->pages {
	Buf = get page PID
	scan Buf for real matches and display each	
}

Abstract Data Type

在這裏插入圖片描述
Bit-string 的索引從0至n-1。
在這裏插入圖片描述
newRelation()中後面6個參數是用於create()和R.info。
addToRelation() 是將tuple加入到relation裏,注意要考慮到無法加入的情況。

在這裏插入圖片描述
startQuery() 返回可能與query相符的pages。
在這裏插入圖片描述
findPagesUsingXsigs需要將結果存到q->pages中。
每種signature都有自己的data type(包括兩個函數),但除了makeBitSliceSig(),因爲它可以被page signature的代替。

Reference

Comp9315 week7a lecture

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