Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Use macros to define the relative costs of search and seek operations when computing costs in the query planner. Current constants seems wrong and need to be fixed, but doing so will alter test results. Need more experimentation to determine accurate relative costs. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
5f2ec44b22062ee9d31e20806fcec010 |
User & Date: | drh 2011-02-09 03:04:27.847 |
Context
2011-02-09
| ||
15:25 | Update Makefile.in for fts3_aux changes. (check-in: 38b7cb33c5 user: shaneh tags: trunk) | |
03:04 | Use macros to define the relative costs of search and seek operations when computing costs in the query planner. Current constants seems wrong and need to be fixed, but doing so will alter test results. Need more experimentation to determine accurate relative costs. (check-in: 5f2ec44b22 user: drh tags: trunk) | |
03:03 | Simplifications to the sqlite3_wal_checkpoint_v2() logic. (check-in: 652b8835c5 user: drh tags: trunk) | |
Changes
Changes to src/where.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ #include "sqliteInt.h" /* ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) int sqlite3WhereTrace = 0; #endif #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ #include "sqliteInt.h" /* ** The following parameter define the relative cost of various ** search operations. These parameters are used to estimate query ** plan costs and to select the query plan with the lowest estimated ** cost. ** ** Let the cost of moving from one row in a table or index to the next ** or previous row be SEEK_COST. ** ** Let the base-10 logarithm of the number of rows in a table or ** index be L. The estLog() function below will estimate this ** numbmer given the number of rows in the table. ** ** The cost of doing a lookup of an index will be IDX_LKUP_COST*L. ** ** The cost of doing a lookup on a table is TBL_LKUP_COST*L. ** ** The cost of sorting a result set of N rows is assumed to be ** N*log10(N)*SORT_COST. */ #if defined(SEEK_COST) /* Assume that IDX_LKUP_COST, TBL_LKUP_COST, and SORT_COST are also defined */ #elif !defined(SQLITE_OMIT_FLOATING_POINT) # define SEEK_COST 1.0 # define IDX_LKUP_COST 1.0 # define TBL_LKUP_COST 0.1 # define SORT_COST 3.0 #else # define SEEK_COST 10 # define IDX_LKUP_COST 10 # define TBL_LKUP_COST 1 # define SORT_COST 30 #endif /* ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) int sqlite3WhereTrace = 0; #endif #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) |
︙ | ︙ | |||
1756 1757 1758 1759 1760 1761 1762 | return; } /* Search for any equality comparison term */ pWCEnd = &pWC->a[pWC->nTerm]; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( termCanDriveIndex(pTerm, pSrc, notReady) ){ | | | 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 | return; } /* Search for any equality comparison term */ pWCEnd = &pWC->a[pWC->nTerm]; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( termCanDriveIndex(pTerm, pSrc, notReady) ){ WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n", pCost->rCost, costTempIdx)); pCost->rCost = costTempIdx; pCost->plan.nRow = logN + 1; pCost->plan.wsFlags = WHERE_TEMP_INDEX; pCost->used = pTerm->prereqRight; break; } |
︙ | ︙ | |||
2732 2733 2734 2735 2736 2737 2738 2739 | /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const unsigned int * const aiRowEst = pProbe->aiRowEst; double cost; /* Cost of using pProbe */ double nRow; /* Estimated number of rows in result set */ int rev; /* True to scan in reverse order */ | > > < | 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 | /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const unsigned int * const aiRowEst = pProbe->aiRowEst; double cost; /* Cost of using pProbe */ double nRow; /* Estimated number of rows in result set */ double nTabSrch; /* Est number of table searches */ double nIdxSrch; /* Est number of index searches */ int rev; /* True to scan in reverse order */ int wsFlags = 0; Bitmask used = 0; /* The following variables are populated based on the properties of ** index being evaluated. They are then used to determine the expected ** cost and number of rows returned. ** |
︙ | ︙ | |||
2950 2951 2952 2953 2954 2955 2956 | if( pIdx ){ if( bLookup ){ /* For an index lookup followed by a table lookup: ** nInMul index searches to find the start of each index range ** + nRow steps through the index ** + nRow table searches to lookup the table entry using the rowid */ | | > | | > | > | > | | | 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 | if( pIdx ){ if( bLookup ){ /* For an index lookup followed by a table lookup: ** nInMul index searches to find the start of each index range ** + nRow steps through the index ** + nRow table searches to lookup the table entry using the rowid */ nIdxSrch = nInMul; nTabSrch = nRow; }else{ /* For a covering index: ** nInMul index searches to find the initial entry ** + nRow steps through the index */ nIdxSrch = nInMul; nTabSrch = 0; } }else{ /* For a rowid primary key lookup: ** nInMult table searches to find the initial entry for each range ** + nRow steps through the table */ nIdxSrch = 0; nTabSrch = nInMul; } cost = nRow + (nIdxSrch*IDX_LKUP_COST + nTabSrch*TBL_LKUP_COST) *estLog(aiRowEst[0])/SEEK_COST; /* Add in the estimated cost of sorting the result. This cost is expanded ** by a fudge factor of 3.0 to account for the fact that a sorting step ** involves a write and is thus more expensive than a lookup step. */ if( bSort ){ cost += nRow*estLog(nRow)*SORT_COST/SEEK_COST; } /**** Cost of using this index has now been computed ****/ /* If there are additional constraints on this table that cannot ** be used with the current index, but which might lower the number ** of output rows, adjust the nRow value accordingly. This only |
︙ | ︙ | |||
3038 3039 3040 3041 3042 3043 3044 | } if( nRow<2 ) nRow = 2; } WHERETRACE(( "%s(%s): nEq=%d nInMul=%d estBound=%d bSort=%d bLookup=%d wsFlags=0x%x\n" | | > | | 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 | } if( nRow<2 ) nRow = 2; } WHERETRACE(( "%s(%s): nEq=%d nInMul=%d estBound=%d bSort=%d bLookup=%d wsFlags=0x%x\n" " notReady=0x%llx nTSrch=%.1f nISrch=%.1f nRow=%.1f\n" " estLog=%.1f cost=%.1f used=0x%llx\n", pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"), nEq, nInMul, estBound, bSort, bLookup, wsFlags, notReady, nTabSrch, nIdxSrch, nRow, estLog(aiRowEst[0]), cost, used )); /* If this index is the best we have seen so far, then record this ** index and its cost in the pCost structure. */ if( (!pIdx || wsFlags) && (cost<pCost->rCost || (cost<=pCost->rCost && nRow<pCost->plan.nRow)) |
︙ | ︙ |