aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2010-11-16 02:49:15 +0000
committerdrh <drh@noemail.net>2010-11-16 02:49:15 +0000
commit95aa47b10a6ff9e920ee82b1dcde8c8ed73c69c2 (patch)
tree9605a6df054b4f999533db6d21fea19693810a40 /src
parent04098e60858effdd49bce4c7550787a61fc39b00 (diff)
downloadsqlite-95aa47b10a6ff9e920ee82b1dcde8c8ed73c69c2.tar.gz
sqlite-95aa47b10a6ff9e920ee82b1dcde8c8ed73c69c2.zip
Use the estimated number of rows computed for subqueries in the cost
computations for outer queries. FossilOrigin-Name: 56bbc539246a6dc9f1ae1edb898db7a4f6f6d322
Diffstat (limited to 'src')
-rw-r--r--src/select.c20
-rw-r--r--src/sqliteInt.h2
-rw-r--r--src/where.c2
3 files changed, 24 insertions, 0 deletions
diff --git a/src/select.c b/src/select.c
index 0f83bbb36..5c5b61589 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1433,6 +1433,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
+ }else{
+ if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
}
}else{
sqlite3ExprCode(pParse, p->pLimit, iLimit);
@@ -1594,6 +1596,7 @@ static int multiSelect(
switch( p->op ){
case TK_ALL: {
int addr = 0;
+ int nLimit;
assert( !pPrior->pLimit );
pPrior->pLimit = p->pLimit;
pPrior->pOffset = p->pOffset;
@@ -1616,6 +1619,13 @@ static int multiSelect(
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
+ p->nSelectRow += pPrior->nSelectRow;
+ if( pPrior->pLimit
+ && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
+ && p->nSelectRow > (double)nLimit
+ ){
+ p->nSelectRow = (double)nLimit;
+ }
if( addr ){
sqlite3VdbeJumpHere(v, addr);
}
@@ -1688,6 +1698,7 @@ static int multiSelect(
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
+ if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
@@ -1767,6 +1778,7 @@ static int multiSelect(
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
+ if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
@@ -2353,6 +2365,7 @@ static int multiSelectOrderBy(
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
+ p->nSelectRow += pPrior->nSelectRow;
}
/* Generate a subroutine to run when the results from select B
@@ -2360,6 +2373,7 @@ static int multiSelectOrderBy(
*/
if( op==TK_INTERSECT ){
addrEofB = addrEofA;
+ if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
}else{
VdbeNoopComment((v, "eof-B subroutine"));
addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
@@ -3754,6 +3768,7 @@ int sqlite3Select(
explainSetInteger(pItem->iSelectId, pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->isPopulated = 1;
+ pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
}
if( /*pParse->nErr ||*/ db->mallocFailed ){
goto select_end;
@@ -3846,6 +3861,7 @@ int sqlite3Select(
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
+ p->nSelectRow = (double)LARGEST_INT64;
computeLimitRegisters(pParse, p, iEnd);
/* Open a virtual index to use for the distinct set.
@@ -3869,6 +3885,7 @@ int sqlite3Select(
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
if( pWInfo==0 ) goto select_end;
+ if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -3913,6 +3930,9 @@ int sqlite3Select(
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
pItem->iAlias = 0;
}
+ if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
+ }else{
+ p->nSelectRow = (double)1;
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b9eb650d8..c02a0e448 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1947,6 +1947,7 @@ struct WhereInfo {
int nLevel; /* Number of nested loop */
struct WhereClause *pWC; /* Decomposition of the WHERE clause */
double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
+ double nRowOut; /* Estimated number of output rows */
WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
@@ -2022,6 +2023,7 @@ struct Select {
Expr *pOffset; /* OFFSET expression. NULL means not used. */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
+ double nSelectRow; /* Estimated number of result rows */
};
/*
diff --git a/src/where.c b/src/where.c
index 1d6641ee8..751c7a99c 100644
--- a/src/where.c
+++ b/src/where.c
@@ -4423,6 +4423,7 @@ WhereInfo *sqlite3WhereBegin(
*/
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
notReady = ~(Bitmask)0;
+ pWInfo->nRowOut = (double)1;
for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
@@ -4430,6 +4431,7 @@ WhereInfo *sqlite3WhereBegin(
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
pLevel->iTabCur = pTabItem->iCursor;
+ pWInfo->nRowOut *= pLevel->plan.nRow;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
/* Do nothing */