From: dan Date: Mon, 30 Mar 2015 12:06:26 +0000 (+0000) Subject: Improve performance of multi-field sorts where the first field has a low cardinality. X-Git-Tag: version-3.8.10~152^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7004f3f6a311398f00d856b359d7389b72f802de;p=thirdparty%2Fsqlite.git Improve performance of multi-field sorts where the first field has a low cardinality. FossilOrigin-Name: 601e7b6b8e6bfabda03b70f75094c9014e3a3c49 --- diff --git a/manifest b/manifest index a3ffa9b4e0..a7a78bf354 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\ssome\sunnecessary\scode\sfrom\svdbesort.c. -D 2015-03-30T09:58:38.613 +C Improve\sperformance\sof\smulti-field\ssorts\swhere\sthe\sfirst\sfield\shas\sa\slow\scardinality. +D 2015-03-30T12:06:26.995 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -294,13 +294,13 @@ F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec F src/vdbe.c bbfede5a8a6908b3ddcd55fdb0b2301288dd4754 -F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 +F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0 F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 -F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907 +F src/vdbeaux.c a20504ae52392459fa08402fda3f195f19d7c79d F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c f283b28d9d1bbaf9c4467c1275ab2146ed868ec9 +F src/vdbesort.c 7b3684665ea51d642b0e664fa4d0b0d08d61d80c F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -1247,7 +1247,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 24fe9f25d64ee516633fed1ae7ebc21554aa69ca -R 7cd5cef35d63d5a82a586382f49d8e50 +P b58191e91736b1d978db4127f22867dfe2302f7c +R ce44a3d54ad53a02b61fed80311cecef U dan -Z 51fc974a93f39baea754c6fb429251e1 +Z 8753c6822202b0898d8492105ecdb751 diff --git a/manifest.uuid b/manifest.uuid index 698dbf4147..2a8f64fa3a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b58191e91736b1d978db4127f22867dfe2302f7c \ No newline at end of file +601e7b6b8e6bfabda03b70f75094c9014e3a3c49 \ No newline at end of file diff --git a/src/vdbe.h b/src/vdbe.h index b715241b41..bb597b68d7 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -213,6 +213,7 @@ int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 9c5d9acca9..1c10bab0b8 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3585,7 +3585,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ ** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the ** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). */ -static int vdbeRecordCompareWithSkip( +int sqlite3VdbeRecordCompareWithSkip( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2, /* Right key */ int bSkip /* If true, skip the first field */ @@ -3771,7 +3771,7 @@ int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ - return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); } @@ -3859,7 +3859,7 @@ static int vdbeRecordCompareInt( }else if( pPKey2->nField>1 ){ /* The first fields of the two keys are equal. Compare the trailing ** fields. */ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ @@ -3907,7 +3907,7 @@ static int vdbeRecordCompareString( res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; } diff --git a/src/vdbesort.c b/src/vdbesort.c index b6483b9ee7..547dce2e65 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -749,6 +749,25 @@ static int vdbePmaReaderInit( return rc; } +/* +** A version of vdbeSorterCompare() that assumes that it has already been +** determined that the first field of key1 is equal to the first field of +** key2. +*/ +static int vdbeSorterCompareTail( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + UnpackedRecord *r2 = pTask->pUnpacked; + if( *pbKey2Cached==0 ){ + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; + } + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); +} + /* ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, ** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences @@ -805,7 +824,9 @@ static int vdbeSorterCompareText( if( res==0 ){ if( pTask->pSorter->pKeyInfo->nField>1 ){ - res = vdbeSorterCompare(pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2); + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); } }else{ if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ @@ -872,7 +893,9 @@ static int vdbeSorterCompareInt( if( res==0 ){ if( pTask->pSorter->pKeyInfo->nField>1 ){ - res = vdbeSorterCompare(pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2); + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); } }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ res = res * -1;