在這個系列的開頭幾篇文章中,曾經介紹了mongodb的查詢流程,因為篇幅所限,並未介紹對cursor進行遍歷查詢時,如何將查詢記錄裝填進結果集中。
今天就針對諸如
select top n
這類返回一定數量記錄的查詢操作,來分析mongodb是如何將查詢結果裝填到結果集中的。這裡要說明的是
之前文章中的大部分程式流程,在select top 這類操作也都是要執行的,所以這裡接著之前文章所說的內容,繼續向底層挖掘相應的功能邏輯。
之前查詢流程中介紹過queryplanset::runner::run()方法,它本身為struct型別,主要是用於對執行步驟進行封裝(形成依次執行的操作流),如下(詳情見注釋):
queryoptimizer.cpp
shared_ptr
<
queryop
>
queryplanset::runner::run()
//將查詢操作集合轉換成查詢佇列
std::priority_queue
<
opholder
>
queue;
for( vector
<
shared_ptr
<
queryop
>
>
::iterator i
=ops.begin(); i
!=ops.end();
++i )
}while( !
queue.empty() )
return
holder._op;}if
( op.error() )
queue.push( holder );
//如未執行完成,再次該查詢操作入隊(尾)
//使用查詢計畫?
if(
!_plans._bestguessonly
&&_plans._usingprerecordedplan
&&op.nscanned()
>
_plans._oldnscanned *10
&&_plans._special.empty() )
_plans._mayrecordplan
=true
;_plans._usingprerecordedplan
=false;}
}return
ops[ 0];
}void
queryplanset::runner::nextop( queryop
&op ) );}
因為userqueryop是queryop的子類,如下圖:
因為本文是userqueryop物件,則上面**段中的nextop()會最終呼叫該物件的next方法:
query.cpp
virtual
void
next()
bool
maycreatecursor1
=_pq.wantmore() &&!
_inmemsort
&&_pq.getnumtoreturn() !=1
&&usecursors;
if( 0)
//判斷是否超出掃瞄項限制,形如:db.foo.find()._addspecial( "$maxscan" , 50 )
if( _pq.getmaxscan()
&&_nscanned
>=
_pq.getmaxscan() )
_nscanned =_c
->
nscanned();
if(
!matcher()
->
matches(_c
->
currkey(), _c
->
currloc() ,
&_details ) )
else
else
if( _c
->
getsetdup(cl) )
else
else
if( _ntoskip
>0)
else
}else
else
if( _keyfieldsonly )
else
//將當前記錄填充到_buf中,以便finish方法使用該物件
fillqueryresultfromobj( _buf , _pq.getfields() , js , (_pq.showdiskloc() ?&
cl :
0));}_n
++;if( !_c
->
supportgetmore() ) }//
判斷是否已夠返回一批資料
else
if( _pq.enoughforfirstbatch( n() , _buf.len() ) ) }//
查詢結束,繫結查詢結果資料到response
finish(
true
);return;}
}}}}
//將游標指向下一條記錄,該方法參見
//_c
->
advance();}
上面**是實現了對相應cursor的遍歷查詢,找出(matches)合適的資料,並最後將結果新增到_buf物件中,之後再使用finish方法將_buf繫結到response中(向client傳送資訊),如下:
query.cpp
//this plan won, so set data for response broadly
void
finish(
bool
stop )
//當使用scanandorder(位於scanandorder.h),表示索引不能用於排序(sort)
else
if( _inmemsort )
if( _c.
get() )
if( _pq.i***plain() )
else}if
( stop )
else}
好了,今天的內容到這裡就告一段落了,最後用一張時序圖來總結一下查詢(select top)在mongodb中的執行流程:
Mongodb原始碼分析
在之前的一篇文章中,介紹了mongos的啟動流程,在那篇文章的結尾,介紹了mongos使用balancer來進行均衡,今天就繼續講其實現方式。可以看到balancer類裡包含乙個balancerpolicy,其指向乙個均衡策略,該策略會實現查詢並收集要遷移的chunk。這裡先看一下balancer的...
MyBatis查詢的原始碼分析
如下為mybatis的乙個集合查詢 string resource mybatis.cfg.xml reader reader resources.getresourceasreader resource sqlsessionfactory ssf new sqlsessionfactorybuil...
Solr查詢過程原始碼分析
searchhandler.handlerequestbody solr搜尋主流程 1.呼叫 requesthandlerbase handlerequest req,rsp 2.原始碼分析 prepare 前期的請求引數準備工作,querycomponent可以在schemal檔案中設定,易擴充套...