標籤:postgresql 程式碼分析 最佳化 查詢最佳化 條件
PostgreSQL程式碼分析,查詢最佳化部分。
張大明白的blog:http://blog.csdn.net/shujiezhang
相關博文:PostgreSQL程式碼分析,查詢最佳化部分,process_duplicate_ors
/* * canonicalize_qual * Convert a qualification expression to the most useful form. * * The name of this routine is a holdover from a time when it would try to * force the expression into canonical AND-of-ORs or OR-of-ANDs form. * Eventually, we recognized that that had more theoretical purity than * actual usefulness, and so now the transformation doesn't involve any * notion of reaching a canonical form. * * NOTE: we assume the input has already been through eval_const_expressions * and therefore possesses AND/OR flatness. Formerly this function included * its own flattening logic, but that requires a useless extra pass over the * tree. * * Returns the modified qualification. *//* * 對WHERE語句或ON語句中的條件進行正常化,從集合的角度對AND和OR兩個操作做合并分解。 */Expr *canonicalize_qual(Expr *qual){Expr *newqual;/* Quick exit for empty qual */if (qual == NULL)return NULL;/* * Pull up redundant subclauses in OR-of-AND trees. We do this only * within the top-level AND/OR structure; there's no point in looking * deeper. *//* * 尋找重複的OR操作,即化簡條件陳述式。 * 假設WHERE條件為: *(A=1 AND B=1) OR (A=1 AND C=1) * 可以化簡為: *A=1 AND (B=1 OR C=1) * * 另外,這個函數中做了將樹狀的AND或OR語句平面化(flatten,或拉平)的工作, * 這兩個工作主要體現在pull_ands()和pull_ors()兩個函數中。 */newqual = find_duplicate_ors(qual);return newqual;}/* * find_duplicate_ors * Given a qualification tree with the NOTs pushed down, search for * OR clauses to which the inverse OR distributive law might apply. * Only the top-level AND/OR structure is searched. * * Returns the modified qualification.AND/OR flatness is preserved. */static Expr *find_duplicate_ors(Expr *qual){/* * “分支一:or_clause” * * 如果WHERE運算式中的主操作是OR,例如是如下形式: *A=1 OR B=1 OR (C=1 AND D=1) * 那麼參數qual指標實際指向一個BoolExpr結構體。typedef struct BoolExpr{Exprxpr; = 略BoolExprType boolop; = OR_EXPR,即對下面的3個進行OR操作List *args; = 3個,分別是A=1和 B=1和(C=1 AND D=1)} BoolExpr; * * 這裡的args是一個list,其中的3個元素的類型分別如下: * 第一個是比較操作,類型是OpExpr * 第二個是比較操作,類型是OpExpr * 第三個是AND操作,是一個AND_EXPR類型的BoolExpr,遞迴調用時會處理 * * 張大明白的blog:http://blog.csdn.net/shujiezhang */if (or_clause((Node *) qual)){List *orlist = NIL;ListCell *temp;/* Recurse *//* * 對BoolExpr中的三個條件分別進行遞迴處理。 * 在這裡需要重點關註上例中的AND_EXPR類型的BoolExpr,因為在遞迴調用中,他將 * 觸發下一個分支(分支二)。 */foreach(temp, ((BoolExpr *) qual)->args)orlist = lappend(orlist, find_duplicate_ors(lfirst(temp)));/* * Don't need pull_ors() since this routine will never introduce an OR * where there wasn't one before.***這個原因沒理解。*** *//* 詳情見《PostgreSQL程式碼分析,查詢最佳化部分,process_duplicate_ors》博文*/return process_duplicate_ors(orlist);}/* * “分支二:and_clause” * * 這裡主要做了兩個操作: *1) 如果子語句中有OR類型的子語句,則遞迴調用find_duplicate_ors,因為 子OR語句中 * 或許也能提取公用項。 *2) 對AND操作進行拉平。 */else if (and_clause((Node *) qual)){List *andlist = NIL;ListCell *temp;/* Recurse *//* * 子語句中存在一系列OR的情況。 * 例如對於: *A=1 AND ((B=1 AND C=1) OR (B=1 AND D=1)) * 這裡的qual指標指向一個AND_EXPR類型的BoolExpr結構體,則 *typedef struct BoolExpr{Exprxpr; = 略BoolExprType boolop; = AND_EXPR,即對下面的2個進行AND操作List *args; = 2個,分別是“A=1”和 “((B=1 AND C=1) OR (B=1 AND D=1))”} BoolExpr; * * 對於其中的“((B=1 AND C=1) OR (B=1 AND D=1))”,在遞迴調用中, * 會進入“分支一:or_clause”,進而轉換為: *B=1 AND (C=1 OR D=1) * * 張大明白的blog:http://blog.csdn.net/shujiezhang */foreach(temp, ((BoolExpr *) qual)->args)andlist = lappend(andlist, find_duplicate_ors(lfirst(temp)));/* Flatten any ANDs introduced just below here *//* * 拉平。 * * 因為主語句是AND類型,子語句也是AND類型,所以可以直接把子語句拉到父節點。 * */andlist = pull_ands(andlist);/* The AND list can't get shorter, so result is always an AND */return make_andclause(andlist);}elsereturn qual;}
PostgreSQL程式碼分析,查詢最佳化部分。
張大明白的blog:http://blog.csdn.net/shujiezhang
相關博文:PostgreSQL程式碼分析,查詢最佳化部分,process_duplicate_ors
PostgreSQL程式碼分析,查詢最佳化部分,canonicalize_qual