From: drh Date: Fri, 8 Nov 2013 16:54:56 +0000 (+0000) Subject: Performance improvement: Avoid unnecessary seeks on REPLACE INTO for a X-Git-Tag: version-3.8.2~126 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=392ee21d1a70dcce453ef95203383927393c3239;p=thirdparty%2Fsqlite.git Performance improvement: Avoid unnecessary seeks on REPLACE INTO for a WITHOUT ROWID table. FossilOrigin-Name: fd11afa5f5c853dcac2290444b581a3fe1d4332d --- diff --git a/manifest b/manifest index e7d399acd1..6bbae7bba9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\simprovements:\nAvoid\sunnecessary\sseeks\swhen\sdoing\sa\ssingle-row\sUPDATE\son\sa\sWITHOUT\sROWID\ntable. -D 2013-11-08T15:19:46.383 +C Performance\simprovement:\sAvoid\sunnecessary\sseeks\son\sREPLACE\sINTO\sfor\sa\nWITHOUT\sROWID\stable. +D 2013-11-08T16:54:56.609 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d12e4455cf7a36e42d3949876c1c3b88ff70867a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -173,7 +173,7 @@ F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c fb896d68bae9a5ee3459c60d8ed929a2b41f7afb +F src/delete.c ddb92f44595366c4817e576b5f11cad5a915c3ef F src/expr.c e7bbe3c6916e141f27a28655d3cf325b817695e4 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5370840745f01f11fb219922d8e99a48ff92fbeb @@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 11d577c152a3304a078d508e5a65031904ed61e7 +F src/insert.c b3218fa5dceeb563485113eff8e1d4c3c59160b0 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -223,7 +223,7 @@ F src/shell.c 03d8d9b4052430343ff30d646334621f980f1202 F src/sqlite.h.in a8cad179541b8d171fed425a737084702ef462ef F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h b4311956d26be8036f5feb2f1c904c313979ea17 +F src/sqliteInt.h 3da1940a2ba05a663e9016d57f1ea1f79ffcb03e F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1135,7 +1135,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 3c566e41e4c9c66960cc5a3ddee8556835237999 -R cbe50e39428754e7aa6f05505b294390 +P 6f187a0fb1b09ebc4732c4afbf3c813f82e069f1 +R eedb71726af8e12f0f13d18d7fd22009 U drh -Z 2b1321d582e3f35ab93369db1373861d +Z 047e6bb9b5b607bfaacf5c7e4c685d04 diff --git a/manifest.uuid b/manifest.uuid index 3cdcec40ae..7a0daf8187 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6f187a0fb1b09ebc4732c4afbf3c813f82e069f1 \ No newline at end of file +fd11afa5f5c853dcac2290444b581a3fe1d4332d \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index a1b626ef4a..4fb3946595 100644 --- a/src/delete.c +++ b/src/delete.c @@ -408,7 +408,7 @@ void sqlite3DeleteFrom( /* Delete the row */ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - iPk, 0, 1, OE_Default); + iPk, 0, 1, OE_Default, 0); /* End of the delete loop */ sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1); @@ -472,7 +472,7 @@ void sqlite3DeleteFrom( { int count = (pParse->nested==0); /* True to count changes */ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - iRowid, 1, count, OE_Default); + iRowid, 1, count, OE_Default, 0); } /* End of the delete loop */ @@ -551,7 +551,8 @@ void sqlite3GenerateRowDelete( int iPk, /* First memory cell containing the PRIMARY KEY */ i16 nPk, /* Number of PRIMARY KEY memory cells */ u8 count, /* If non-zero, increment the row change counter */ - u8 onconf /* Default ON CONFLICT policy for triggers */ + u8 onconf, /* Default ON CONFLICT policy for triggers */ + u8 bNoSeek /* iDataCur is already pointing to the row to delete */ ){ Vdbe *v = pParse->pVdbe; /* Vdbe */ int iOld = 0; /* First register in OLD.* array */ @@ -568,7 +569,7 @@ void sqlite3GenerateRowDelete( ** not attempt to delete it or fire any DELETE triggers. */ iLabel = sqlite3VdbeMakeLabel(v); opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); + if( !bNoSeek ) sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); /* If there are any triggers to fire, allocate a range of registers to ** use for the old.* references in the triggers. */ @@ -672,18 +673,17 @@ void sqlite3GenerateRowIndexDelete( Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */ v = pParse->pVdbe; - VdbeModuleComment((v, "BEGIN: GenRowIdxDel(%d,%d)", iDataCur, iIdxCur)); pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ assert( iIdxCur+i!=iDataCur || pPk==pIdx ); if( aRegIdx!=0 && aRegIdx[i]==0 ) continue; if( pIdx==pPk ) continue; + VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName)); r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, &iPartIdxLabel); sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); sqlite3VdbeResolveLabel(v, iPartIdxLabel); } - VdbeModuleComment((v, "END: GenRowIdxDel()")); } /* diff --git a/src/insert.c b/src/insert.c index d789d298c9..7235370a53 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1408,7 +1408,7 @@ void sqlite3GenerateConstraintChecks( if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - regNewData, 1, 0, OE_Replace); + regNewData, 1, 0, OE_Replace, 1); }else if( pTab->pIndex ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0); @@ -1498,11 +1498,11 @@ void sqlite3GenerateConstraintChecks( } /* Check to see if the new index entry will be unique */ - regR = sqlite3GetTempRange(pParse, nPkField); sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, regIdx, pIdx->nKeyCol); /* Generate code to handle collisions */ + regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); if( HasRowid(pTab) ){ sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR); /* Conflict only if the rowid of the existing index entry @@ -1514,7 +1514,7 @@ void sqlite3GenerateConstraintChecks( int x; /* Extract the PRIMARY KEY from the end of the index entry and ** store it in registers regR..regR+nPk-1 */ - if( isUpdate || onError==OE_Replace ){ + if( (isUpdate || onError==OE_Replace) && pIdx!=pPk ){ for(i=0; inKeyCol; i++){ x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); @@ -1547,7 +1547,6 @@ void sqlite3GenerateConstraintChecks( } } } - sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn); /* Generate code that executes if the new index entry is not unique */ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail @@ -1571,13 +1570,14 @@ void sqlite3GenerateConstraintChecks( pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - regR, nPkField, 0, OE_Replace); + regR, nPkField, 0, OE_Replace, pIdx==pPk); seenReplace = 1; break; } } sqlite3VdbeResolveLabel(v, addrUniqueOk); - sqlite3ReleaseTempRange(pParse, regR, nPkField); + sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn); + if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } if( ipkTop ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, ipkTop+1); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 934ba3c965..0ae55edf3d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2930,7 +2930,7 @@ int sqlite3ExprCanBeNull(const Expr*); void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); -void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8); +void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,