Change the way samples for the sqlite_stat4 table are collected.

FossilOrigin-Name: 13ed5ac13562e7a39905d70fd47059f4d8001bba
This commit is contained in:
dan 2013-08-07 16:15:32 +00:00
parent 7ed103210d
commit 1f28eaddc4
3 changed files with 49 additions and 33 deletions

View File

@ -1,5 +1,5 @@
C Fix\sthe\s".dump"\scommand\son\sthe\scommand-line\sshell\sso\sthat\sit\sworks\sfor\n"sqlite_stat4"\sin\saddition\sto\s"sqlite_stat1".
D 2013-08-07T16:04:27.058
C Change\sthe\sway\ssamples\sfor\sthe\ssqlite_stat4\stable\sare\scollected.
D 2013-08-07T16:15:32.765
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
F src/analyze.c b8b0d15347ae34772f0df9b6d02848dea9dfe8a3
F src/analyze.c 8dfc6a70274314bcb0ba41d218e840a5591dd895
F src/attach.c 1816f5a9eea8d2010fc2b22b44f0f63eb3a62704
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 43b348822db3e4cef48b2ae5a445fbeb6c73a165
@ -1106,7 +1106,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P 9159b43eb2cb5d6ed18a5ad168fa27134fec2553
R f3f1a72dd300dcd2969e458028afbec5
U drh
Z 194a793cc38dc0b3add1e00828469db6
P 1e80c4b12dbb5beab422e2a33a8782ac9d767321
R 872f61a83df4a029ddba5de7545c74a2
U dan
Z ad2d3dd84452de28ba71d37d31a2a3f2

View File

@ -1 +1 @@
1e80c4b12dbb5beab422e2a33a8782ac9d767321
13ed5ac13562e7a39905d70fd47059f4d8001bba

View File

@ -218,14 +218,13 @@ typedef struct Stat4Accum Stat4Accum;
struct Stat4Accum {
tRowcnt nRow; /* Number of rows in the entire table */
tRowcnt nPSample; /* How often to do a periodic sample */
int iMin; /* Index of entry with minimum nSumEq and hash */
int iMin; /* Index of entry with minimum nEq and hash */
int mxSample; /* Maximum number of samples to accumulate */
int nSample; /* Current number of samples */
int nCol; /* Number of columns in the index */
u32 iPrn; /* Pseudo-random number used for sampling */
struct Stat4Sample {
i64 iRowid; /* Rowid in main table of the key */
tRowcnt nSumEq; /* Sum of anEq[] values */
tRowcnt *anEq; /* sqlite_stat4.nEq */
tRowcnt *anLt; /* sqlite_stat4.nLt */
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
@ -349,23 +348,38 @@ static void stat4Push(
assert( p->nCol>0 );
assert( argc==(2 + 3*p->nCol) );
/* Set nSumEq to the sum of all nEq parameters. */
for(i=0; i<p->nCol; i++){
nSumEq += sqlite3_value_int64(aEq[i]);
}
if( nSumEq==0 ) return;
/* Figure out if this sample will be used. Set isPSample to true if this
** is a periodic sample, or false if it is being captured because of a
** large nSumEq value. If the sample will not be used, return early. */
/* Figure out if this sample will be used. There are two reasons a
** sample may be used:
**
** 1. It may be a periodic sample. In this case set isPSample to true
** as well. Or,
**
** 2. Less than p->mxSample samples have been collected so far, or
**
** 3. It is more desirable than some other non-periodic sample that has
** already been collected. Samples are compared based on the values
** in the anEq array, starting from last (right-most index column)
** to first (left-most index column). If all elements of the anEq
** array are equal, samples are compared by hash value.
*/
h = p->iPrn = p->iPrn*1103515245 + 12345;
if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){
doInsert = isPSample = 1;
}else if( (p->nSample<p->mxSample)
|| (nSumEq>p->a[iMin].nSumEq)
|| (nSumEq==p->a[iMin].nSumEq && h>p->a[iMin].iHash)
){
}else if( p->nSample<p->mxSample ){
doInsert = 1;
}else{
tRowcnt *aMinEq = p->a[iMin].anEq;
for(i=p->nCol-1; i>=0; i--){
i64 nEq = sqlite3_value_int64(aEq[i]);
if( nEq<aMinEq[i] ) break;
if( nEq>aMinEq[i] ){
doInsert = 1;
break;
}
}
if( i<0 && h>p->a[iMin].iHash ){
doInsert = 1;
}
}
if( !doInsert ) return;
@ -387,7 +401,6 @@ static void stat4Push(
pSample->iRowid = rowid;
pSample->iHash = h;
pSample->isPSample = isPSample;
pSample->nSumEq = nSumEq;
for(i=0; i<p->nCol; i++){
pSample->anEq[i] = sqlite3_value_int64(aEq[i]);
pSample->anLt[i] = sqlite3_value_int64(aLt[i]);
@ -397,18 +410,21 @@ static void stat4Push(
/* Find the new minimum */
if( p->nSample==p->mxSample ){
u32 iHash = 0; /* Hash corresponding to iMin/nSumEq entry */
i64 nMinEq = LARGEST_INT64; /* Smallest nSumEq seen so far */
assert( iMin = -1 );
iMin = -1;
for(i=0; i<p->mxSample; i++){
if( p->a[i].isPSample ) continue;
if( (p->a[i].nSumEq<nMinEq)
|| (p->a[i].nSumEq==nMinEq && p->a[i].iHash<iHash)
){
if( iMin<0 ){
iMin = i;
nMinEq = p->a[i].nSumEq;
iHash = p->a[i].iHash;
}else{
int j;
for(j=p->nCol-1; j>=0; j++){
i64 iCmp = (p->a[iMin].anEq[j] - p->a[i].anEq[j]);
if( iCmp<0 ){ iMin = i; }
if( iCmp ) break;
}
if( j==0 && p->a[iMin].iHash<p->a[i].iHash ){
iMin = i;
}
}
}
assert( iMin>=0 );