WEB开发网
开发学院数据库MySQL 浅谈SQLite——查询处理及优化 阅读

浅谈SQLite——查询处理及优化

 2010-06-25 00:00:00 来源:WEB开发网   
核心提示: 而对于每一层的优化,基本的理念就是对于该层循环的表,浅谈SQLite——查询处理及优化(6),分析WHERE子句中是否有表达式能够使用其索引,Sqlite有三种基本的扫描策略:(1)全表扫描,第三种情况与第二种情况没有什么本质的差别,所以,这种情况通常出现在没有WHERE子句时;(2)基于索引扫

而对于每一层的优化,基本的理念就是对于该层循环的表,分析WHERE子句中是否有表达式能够使用其索引。

Sqlite有三种基本的扫描策略:

(1)全表扫描,这种情况通常出现在没有WHERE子句时;

(2)基于索引扫描,这种情况通常出现在表有索引,而且WHERE中的表达式又能够使用该索引的情况;

(3)基本rowid的扫描,这种情况通常出现在WHERE表达式中含有rowid的条件。该情况实际上也是对表进行的扫描。可以说,Sqlite以rowid为聚簇索引。

第一种情况比较简单,第三种情况与第二种情况没有什么本质的差别。所以,这里只对第二种情况进行详细讨论。

先来看看sqlite3WhereBegin的代码(去掉了一些无关紧要的代码):

 1 /*分析where子句的所有表达式.如果表达式的形式为X <op> Y,则增加一个Y <op> X形式的虚Term,并在后面进行单独分析.
 2    * */
 3   exprAnalyzeAll(pTabList, pWC);
 4 
 5   WHERETRACE(("*** Optimizer Start ***\n"));
 6   //优化开始
 7   for(i=iFrom=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
 8     WhereCost bestPlan;         /* Most efficient plan seen so far */
 9     Index *pIdx;                /* Index for FROM table at pTabItem */
10     int j;                      /* For looping over FROM tables */
11     int bestJ = -1;             /* The value of j */
12     Bitmask m;                  /* Bitmask value for j or bestJ */
13     int isOptimal;              /* Iterator for optimal/non-optimal search */
14 
15     memset(&bestPlan, 0, sizeof(bestPlan));
16     bestPlan.rCost = SQLITE_BIG_DBL;
17 
18     /*进行两次扫描:*/
19 //如果第一次扫描没有找到优化的扫描策略,此时,isOptimal ==0, bestJ ==-1,则进行第二次扫描
20     for(isOptimal=1; isOptimal>=0 && bestJ<0; isOptimal--){
21 //第一次扫描的mask ==0,表示所有表都已经准备好
22       Bitmask mask = (isOptimal ? 0 : notReady);
23       assert( (nTabList-iFrom)>1 || isOptimal );
24       
25       for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
26         int doNotReorder;    /* True if this table should not be reordered */
27         WhereCost sCost;     /* Cost information from best[Virtual]Index() */
28         ExprList *pOrderBy;  /* ORDER BY clause for index to optimize */
29 
30 //对于左连接和交叉连接,不能改变嵌套的顺序
31         doNotReorder =  (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
32         
33         if( j!=iFrom && doNotReorder ) //如果j == iFrom,仍要进行优化处理(此时,是第一次处理iFrom项)
34             break;
35         m = getMask(pMaskSet, pTabItem->iCursor);
36         if( (m & notReady)==0 ){//如果该pTabItem已经进行处理,则不需要再处理
37           if( j==iFrom ) 
38               iFrom++;
39           continue;
40         }
41         pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
42 
43         {
44 //对一个表(pTabItem),找到它的可用于本次查询的最好的索引,sCost返回对应的代价
45           bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost);
46         }
47           if( (sCost.used¬Ready)==0
48          && (j==iFrom || sCost.rCost<bestPlan.rCost) 
49         ){
50           bestPlan = sCost;
51           bestJ = j; //如果bestJ >=0,表示找到了优化的扫描策略
52         }
53         if( doNotReorder ) break;
54       }//end for
55     }//end for
56     WHERETRACE(("*** Optimizer selects table %d for loop %d\n", bestJ,
57            pLevel-pWInfo->a));
58     
59     if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){//不需要进行排序操作
60       *ppOrderBy = 0;
61     }
62 //设置该层选用的查询策略
63     andFlags &= bestPlan.plan.wsFlags;
64 pLevel->plan = bestPlan.plan;
65 
66 //如果可以使用索引,则设置索引对应的游标的下标    
67     if( bestPlan.plan.wsFlags & WHERE_INDEXED ){
68       pLevel->iIdxCur = pParse->nTab++;
69     }else{
70       pLevel->iIdxCur = -1;
71     }
72     notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
73     //该层对应的FROM的表项,即该层循环是对哪个表进行的操作.
74     pLevel->iFrom = (u8)bestJ;
75 
76   }
77   //优化结束
78   WHERETRACE(("*** Optimizer Finished ***\n"));
79

上一页  1 2 3 4 5 6 7 8 9 10  下一页

Tags:SQLite 查询处 理及

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接