浅谈SQLite——查询处理及优化
2010-06-25 00:00:00 来源:WEB开发网非常简单,对于我们的例子,最外层循环students是全表扫描,生成指令7。
利用索引的等值/范围查询:
这种情况相对来说比较复杂(不过读懂了也很简单),对于我们的例子,中间循环sc表,用到索引,指令8~14是对应的opcode。内层循环course表也用到索引,指令15~21是对应的opcode。(具体的含义见其注释,其生成算法见源码)。
这里不得不提到一点。在通用数据库中,连接操作会生成所谓的结果集(用临时表存储)。而sqlite不会生成中间结果集,例如,对这里的例子,它会分别对 students、sc和course各分配一个游标,每次调用接口sqlite3_step时,游标根据where条件分别定位到各自的记录,然后取出查询输出列的数据,放到用于存放结果的寄存器中(见(3)中的opcode)。所以,sqlite中,必须不断调用sqlite3_step才能读取所有记录。
4、selectInnerLoop
该函数主要生成输出结果列的opcode,见(3),比较简单。
5、sqlite3WhereEnd
主要完成嵌套循环的收尾工作的opcode生成,为每层循环生成OP_Next/OP_Prev,以及关闭表和索引游标的OP_Close,也比较简单。
6、SQLite的代价模型
最后,来看看bestBtreeIndex,在这个函数中,完成查询代价的计算以及查询策略的确定。
SQLite采用基于代价的优化。根据处理查询时CPU和磁盘I/O的代价,主要考虑以下一些因素:
A、查询读取的记录数;
B、结果是否排序(这可能会导致使用临时表);
C、是否需要访问索引和原表。
static void bestBtreeIndex(
Parse *pParse, /* The parsing context */
WhereClause *pWC, /* The WHERE clause */
struct SrcList_item *pSrc, /* The FROM clause term to search */
Bitmask notReady, /* Mask of cursors that are not available */
ExprList *pOrderBy, /* The ORDER BY clause */
WhereCost *pCost /* Lowest cost query plan */
)
更多精彩
赞助商链接