利用C++實(shí)現(xiàn)?然連接操作算法
1. 實(shí)驗(yàn)?zāi)康?/h2>
本次實(shí)驗(yàn)三需要完成的內(nèi)容為實(shí)現(xiàn)然連接(natural join)操作算法,對(duì)兩個(gè)關(guān)系進(jìn)然連接,具體實(shí)現(xiàn)基于塊的嵌套循環(huán)連接(Block-based Nested Loop Join)算法。
我們要實(shí)現(xiàn)的函數(shù)在 executer.cpp 文件中。
bool NestedLoopJoinOperator::execute(int numAvailableBufPages, File &resultFile)
2. 實(shí)驗(yàn)內(nèi)容
首先,我們讀取兩個(gè)表頭的信息
TableId leftTableId = catalog->getTableId("r"); TableId rightTableId = catalog->getTableId("s"); badgerdb::File left = File::open(catalog->getTableFilename(leftTableId)); badgerdb::File right = File::open(catalog->getTableFilename(rightTableId));
運(yùn)用兩層循環(huán)尋找兩個(gè)表中名稱與類型完全相同的屬性,將他們?nèi)繕?biāo)記出來(lái),用于之后的自然連接操作。
vector<int> leftForeignKeyId; vector<int> rightForeignKeyId; for (int i = 0; i < leftTableSchema.getAttrCount(); i++) { for (int j = 0; j < rightTableSchema.getAttrCount(); j++) { if ((leftTableSchema.getAttrName(i) == rightTableSchema.getAttrName(j)) && (leftTableSchema.getAttrType(i) == rightTableSchema.getAttrType(j))) { leftForeignKeyId.push_back(i); rightForeignKeyId.push_back(j); break; } } }
準(zhǔn)備操作做完后,開(kāi)始進(jìn)行自然連接操作。
用循環(huán)從磁盤中讀取兩個(gè)頁(yè)面的信息,記錄 io 操作次數(shù)
for (badgerdb::FileIterator leftPage = left.begin(); leftPage != left.end(); leftPage++) { badgerdb::Page *bufferedLeftPage; bufMgr->readPage(&left, (*leftPage).page_number(), bufferedLeftPage); numIOs += 1; for (badgerdb::FileIterator rightPage = right.begin(); rightPage != right.end(); rightPage++) { badgerdb::Page *bufferedRightPage; bufMgr->readPage(&right, (*rightPage).page_number(), bufferedRightPage); numIOs += 1;
之后,從表中讀取全部的元組的信息,進(jìn)行對(duì)比。
讀取的元組信息有特殊的格式,并不能直接利用,所以需要先了解元組在表中儲(chǔ)存的格式,然后進(jìn)行解讀。元組的存儲(chǔ)方式可以從 storage.cpp 中的 createTupleFromSQLStatement 函數(shù)中得知。
switch (dataType) { // (int) 56 (0011 1000) -> (char) '\0''\0''\0''8' case INT: { // convert int value into 4 byte representation case CHAR: { // (char(5) ) 'abc' -> 'abc00' case VARCHAR: { // (varchar(8) ) 'abc' -> '3''abc' (3 refer to the ascii // code number correspond alpha)
于是,我們根據(jù)注釋的存儲(chǔ)方式編寫解析函數(shù),該函數(shù)輸入為文件中存儲(chǔ)的元組,輸出為數(shù)組表示的直觀的元組內(nèi)容。
vector<string> analyze(string record, badgerdb::TableSchema schema)
先讀取其中一個(gè)表的元組,用塊來(lái)存儲(chǔ)。
for (badgerdb::PageIterator leftRecord = bufferedLeftPage->begin(); leftRecord != bufferedLeftPage->end(); leftRecord++) { vector<string> leftInfo = analyze(*leftRecord, leftTableSchema); numUsedBufPages += 1; block.push_back(leftInfo); if (block.size() < BLOCK_SIZE) { continue; }
然后讀取另一個(gè)表的元組信息,
for (badgerdb::PageIterator rightRecord = bufferedRightPage->begin(); rightRecord != bufferedRightPage->end(); rightRecord++) { numUsedBufPages += 1;
將兩個(gè)元組當(dāng)中的屬性名相同的屬性列信息進(jìn)行對(duì)比,
bool f = true; for(int i = 0; i < leftForeignKeyId.size(); i++) { if(leftInfo[leftForeignKeyId[i]] != rightInfo[rightForeignKeyId[i]]) { f = false; break; } }
如果全部相同,則代表需要進(jìn)行自然連接操作。
if(f) { string current_line = "INSERT INTO TEMP_TABLE VALUES (" + leftInfo[0]; for (int i = 1; i < leftTableSchema.getAttrCount(); i++) { current_line = current_line + ", " + leftInfo[i]; } for (int i = 0; i < rightTableSchema.getAttrCount(); i++) { current_line = current_line + ", " + rightInfo[i]; } current_line = current_line + ");"; string tuple = HeapFileManager::createTupleFromSQLStatement(current_line, catalog); numResultTuples += 1; HeapFileManager::insertTuple(tuple, resultFile, bufMgr); }
否則不進(jìn)行任何操作。
在全部循環(huán)都結(jié)束之后,塊中可能還會(huì)有剩余的信息沒(méi)有進(jìn)行處理,此時(shí)再單獨(dú)對(duì)剩余信息進(jìn)行處理,代碼基本相同。
3. 實(shí)驗(yàn)結(jié)果
代碼運(yùn)行結(jié)果如下:
到此這篇關(guān)于利用C++實(shí)現(xiàn)?然連接操作算法的文章就介紹到這了,更多相關(guān)C++連接操作算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
探討:將兩個(gè)鏈表非降序合并為一個(gè)鏈表并依然有序的實(shí)現(xiàn)方法
本篇文章是對(duì)將兩個(gè)鏈表非降序合并為一個(gè)鏈表并依然有序的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C++?QT實(shí)現(xiàn)獲取本機(jī)網(wǎng)卡信息
這篇文章主要為大家詳細(xì)介紹了如何利用qt自帶的QNetworkInterface接口以及c++Iphlpapi庫(kù),獲取當(dāng)前windows電腦下的網(wǎng)卡信息,需要的可以參考下2024-01-01Matlab實(shí)現(xiàn)繪制高階版本韋恩圖(upset圖)
韋恩圖隨著階數(shù)升高會(huì)越來(lái)越復(fù)雜,當(dāng)階數(shù)達(dá)到7或者以上時(shí)幾乎沒(méi)辦法繪制,但是使用upset圖卻可以比較輕易的繪制。本文就來(lái)用Matlab實(shí)現(xiàn)繪制upset圖,需要的可以參考一下2023-01-01C語(yǔ)言靜態(tài)鏈表和動(dòng)態(tài)鏈表
靜態(tài)鏈表和動(dòng)態(tài)鏈表是線性表鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)的兩種不同的表示方式。靜態(tài)鏈表的初始長(zhǎng)度一般是固定的,在做插入和刪除操作時(shí)不需要移動(dòng)元素,僅需修改指針。動(dòng)態(tài)鏈表是相對(duì)于靜態(tài)鏈表而言的,一般地,在描述線性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)時(shí)如果沒(méi)有特別說(shuō)明即默認(rèn)描述的是動(dòng)態(tài)鏈表。2016-05-05基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷游戲
這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10C語(yǔ)言實(shí)現(xiàn)掃雷游戲(可展開(kāi))
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)掃雷游戲,實(shí)現(xiàn)掃雷展開(kāi)和提醒,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03C++ 在堆上開(kāi)辟與釋放二維、三維指針詳細(xì)解析
一維指針其實(shí)就相當(dāng)于一維數(shù)組,不用去看書上所說(shuō)的數(shù)組在內(nèi)存中的首地址這些晦澀的話,以此類推 二維指針就相當(dāng)于二維數(shù)組,新手對(duì)一維數(shù)組的開(kāi)辟與釋放比較容易熟悉2013-09-09