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

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