Add a way for virtual tables to return the expected number of rows for a scan (not just the overall cost) to SQLite. Have the rtree module make use of this.

FossilOrigin-Name: 5a3cfd747a85480d215784817c3821d87ecfa2f7
This commit is contained in:
dan
2013-11-11 19:01:33 +00:00
parent 4308e348d7
commit a9f5815b67
7 changed files with 213 additions and 24 deletions
+18 -5
View File
@@ -5290,10 +5290,22 @@ struct sqlite3_module {
** the correct order to satisfy the ORDER BY clause so that no separate
** sorting step is required.
**
** ^The estimatedCost value is an estimate of the cost of doing the
** particular lookup. A full scan of a table with N entries should have
** a cost of N. A binary search of a table of N entries should have a
** cost of approximately log(N).
** ^The estimatedCost value is an estimate of the cost of a particular
** strategy. A cost of N indicates that the cost of the strategy is similar
** to a linear scan of an SQLite table with N rows. A cost of log(N)
** indicates that the expense of the operation is similar to that of a
** binary search on a unique indexed field of an SQLite table with N rows.
**
** ^The estimatedRows value is an estimate of the number of rows that
** will be returned by the strategy.
**
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
** structure for SQLite version 3.8.2. If a virtual table extension is
** used with an SQLite version earlier than 3.8.2, the results of attempting
** to read or write the estimatedRows field are undefined (but are likely
** to included crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002.
*/
struct sqlite3_index_info {
/* Inputs */
@@ -5318,7 +5330,8 @@ struct sqlite3_index_info {
char *idxStr; /* String, possibly obtained from sqlite3_malloc */
int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
int orderByConsumed; /* True if output is already ordered */
double estimatedCost; /* Estimated cost of using this index */
double estimatedCost; /* Estimated cost of using this index */
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
};
/*
+3 -2
View File
@@ -1978,6 +1978,7 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr);
sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed);
sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost);
sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
}
#else
#define TRACE_IDX_INPUTS(A)
@@ -4787,6 +4788,7 @@ static int whereLoopAddVirtual(
pIdxInfo->needToFreeIdxStr = 0;
pIdxInfo->orderByConsumed = 0;
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
pIdxInfo->estimatedRows = 25;
rc = vtabBestIndex(pParse, pTab, pIdxInfo);
if( rc ) goto whereLoopAddVtab_exit;
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
@@ -4846,8 +4848,7 @@ static int whereLoopAddVirtual(
&& pIdxInfo->orderByConsumed);
pNew->rSetup = 0;
pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
/* TUNING: Every virtual table query returns 25 rows */
pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
whereLoopInsert(pBuilder, pNew);
if( pNew->u.vtab.needFree ){
sqlite3_free(pNew->u.vtab.idxStr);