Skip to content

Commit 3348431

Browse files
authored
Merge pull request #1036 from dolthub/perf/composite-types-next
Avoid duplicate seek for single-row inserts
2 parents 3f95ec5 + 1257efb commit 3348431

1 file changed

Lines changed: 56 additions & 131 deletions

File tree

src/prolly_mutate.c

Lines changed: 56 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -590,10 +590,16 @@ static int rewriteAncestorSpine(
590590
if( countDelta<0 && cnt==0 ){
591591
rc = SQLITE_CORRUPT;
592592
}else{
593+
u64 newCnt = cnt;
594+
if( countDelta<0 ){
595+
newCnt--;
596+
}else if( countDelta>0 ){
597+
newCnt++;
598+
}
593599
prollyNodeKey(pNode, i, &pKey, &nKey);
594600
rc = prollyNodeBuilderAddWithCount(
595601
&b, pKey, nKey, pChildHash->data, PROLLY_HASH_SIZE,
596-
countDelta<0 ? cnt - 1 : cnt + 1);
602+
newCnt);
597603
}
598604
}else{
599605
rc = appendNodeEntryToBuilder(&b, pNode, i, cnt);
@@ -613,12 +619,11 @@ static int rewriteAncestorSpine(
613619
return SQLITE_OK;
614620
}
615621

616-
/* Replace one existing row when node boundaries cannot change. */
617-
static int tryReplaceSingleSameSize(ProllyMutator *pMut){
622+
static int tryInsertOrReplaceSingleNoRechunk(ProllyMutator *pMut){
618623
ProllyMutMapEntry *pEdit;
619624
ProllyCursor cur;
620625
ProllyHash childHash;
621-
i64 iKey;
626+
i64 iKey = 0;
622627
int rc;
623628
int res = 0;
624629
int level;
@@ -646,13 +651,13 @@ static int tryReplaceSingleSameSize(ProllyMutator *pMut){
646651
prollyCursorClose(&cur);
647652
return rc;
648653
}
649-
if( res!=0 || cur.eState!=PROLLY_CURSOR_VALID ){
654+
if( cur.eState!=PROLLY_CURSOR_VALID ){
650655
prollyCursorClose(&cur);
651656
return SQLITE_NOTFOUND;
652657
}
653658

654659
level = cur.iLevel;
655-
{
660+
if( res==0 ){
656661
ProllyNode *pLeaf = &cur.aLevel[level].pEntry->node;
657662
int idx = cur.aLevel[level].idx;
658663
const u8 *pOldVal;
@@ -686,107 +691,53 @@ static int tryReplaceSingleSameSize(ProllyMutator *pMut){
686691
prollyCursorClose(&cur);
687692
return rc;
688693
}
689-
}
690694

691-
while( level>0 ){
692-
ProllyNode *pNode;
695+
rc = rewriteAncestorSpine(pMut, &cur, level, &childHash, 0);
696+
if( rc==SQLITE_OK ){
697+
pMut->newRoot = childHash;
698+
}
699+
prollyCursorClose(&cur);
700+
return rc;
701+
}else{
702+
ProllyNode *pLeaf;
693703
ProllyNodeBuilder b;
694-
ProllyHash parentHash;
695704
int idx;
705+
int requireBoundary;
696706
int i;
697707

698-
level--;
699-
pNode = &cur.aLevel[level].pEntry->node;
700-
idx = cur.aLevel[level].idx;
701-
prollyNodeBuilderInit(&b, (u8)pNode->level, pMut->flags);
702-
for(i=0; i<(int)pNode->nItems; i++){
703-
u64 cnt = 0;
704-
rc = parentChildSubtreeCount(pMut->pStore, pMut->pCache,
705-
pNode, i, &cnt);
706-
if( rc==SQLITE_OK ){
707-
if( i==idx ){
708-
const u8 *pKey;
709-
int nKey;
710-
prollyNodeKey(pNode, i, &pKey, &nKey);
711-
rc = prollyNodeBuilderAddWithCount(
712-
&b, pKey, nKey, childHash.data, PROLLY_HASH_SIZE, cnt);
713-
}else{
714-
rc = appendNodeEntryToBuilder(&b, pNode, i, cnt);
715-
}
708+
if( pMut->flags & PROLLY_NODE_INTKEY ){
709+
if( iKey>=prollyCursorIntKey(&cur) ){
710+
prollyCursorClose(&cur);
711+
return SQLITE_NOTFOUND;
716712
}
717-
if( rc!=SQLITE_OK ){
718-
prollyNodeBuilderFree(&b);
713+
}else{
714+
const u8 *pCurKey;
715+
int nCurKey;
716+
prollyCursorKey(&cur, &pCurKey, &nCurKey);
717+
if( compareKeys(pEdit->pKey, pEdit->nKey, pCurKey, nCurKey)>=0 ){
719718
prollyCursorClose(&cur);
720-
return rc;
719+
return SQLITE_NOTFOUND;
721720
}
722721
}
723-
rc = writeBuilderNode(pMut->pStore, &b, &parentHash);
724-
prollyNodeBuilderFree(&b);
725-
if( rc!=SQLITE_OK ){
726-
prollyCursorClose(&cur);
727-
return rc;
728-
}
729-
childHash = parentHash;
730-
}
731722

732-
pMut->newRoot = childHash;
733-
prollyCursorClose(&cur);
734-
return SQLITE_OK;
735-
}
736-
737-
static int tryDeleteSingleNoRechunk(ProllyMutator *pMut){
738-
ProllyMutMapEntry *pEdit;
739-
ProllyCursor cur;
740-
ProllyHash childHash;
741-
i64 iKey;
742-
int rc;
743-
int res = 0;
744-
int level;
745-
746-
if( prollyHashIsEmpty(&pMut->oldRoot) ) return SQLITE_NOTFOUND;
747-
if( prollyMutMapCount(pMut->pEdits)!=1 ) return SQLITE_NOTFOUND;
748-
749-
pEdit = &pMut->pEdits->aEntries[0];
750-
if( pEdit->op!=PROLLY_EDIT_DELETE ){
751-
return SQLITE_NOTFOUND;
752-
}
753-
if( (pMut->flags & PROLLY_NODE_INTKEY) && pEdit->nKey!=8 ){
754-
return SQLITE_NOTFOUND;
755-
}
756-
757-
prollyCursorInit(&cur, pMut->pStore, pMut->pCache, &pMut->oldRoot,
758-
pMut->flags);
759-
if( pMut->flags & PROLLY_NODE_INTKEY ){
760-
iKey = prollyMutMapEntryIntKey(pEdit);
761-
rc = prollyCursorSeekInt(&cur, iKey, &res);
762-
}else{
763-
rc = prollyCursorSeekBlob(&cur, pEdit->pKey, pEdit->nKey, &res);
764-
}
765-
if( rc!=SQLITE_OK ){
766-
prollyCursorClose(&cur);
767-
return rc;
768-
}
769-
if( res!=0 || cur.eState!=PROLLY_CURSOR_VALID ){
770-
prollyCursorClose(&cur);
771-
return SQLITE_NOTFOUND;
772-
}
773-
774-
level = cur.iLevel;
775-
{
776-
ProllyNode *pLeaf = &cur.aLevel[level].pEntry->node;
777-
int idx = cur.aLevel[level].idx;
778-
ProllyNodeBuilder b;
779-
int requireBoundary;
780-
int i;
781-
782-
if( pLeaf->nItems<=1 || idx==(int)pLeaf->nItems - 1 ){
723+
pLeaf = &cur.aLevel[level].pEntry->node;
724+
idx = cur.aLevel[level].idx;
725+
if( idx<0 || idx>=(int)pLeaf->nItems ){
783726
prollyCursorClose(&cur);
784727
return SQLITE_NOTFOUND;
785728
}
786729

787730
prollyNodeBuilderInit(&b, 0, pMut->flags);
788731
for(i=0; i<(int)pLeaf->nItems; i++){
789-
if( i==idx ) continue;
732+
if( i==idx ){
733+
rc = prollyNodeBuilderAdd(&b, pEdit->pKey, pEdit->nKey,
734+
pEdit->pVal, pEdit->nVal);
735+
if( rc!=SQLITE_OK ){
736+
prollyNodeBuilderFree(&b);
737+
prollyCursorClose(&cur);
738+
return rc;
739+
}
740+
}
790741
rc = appendNodeEntryToBuilder(&b, pLeaf, i, 0);
791742
if( rc!=SQLITE_OK ){
792743
prollyNodeBuilderFree(&b);
@@ -802,21 +753,21 @@ static int tryDeleteSingleNoRechunk(ProllyMutator *pMut){
802753
prollyCursorClose(&cur);
803754
return rc;
804755
}
805-
}
806756

807-
rc = rewriteAncestorSpine(pMut, &cur, level, &childHash, -1);
808-
if( rc==SQLITE_OK ){
809-
pMut->newRoot = childHash;
757+
rc = rewriteAncestorSpine(pMut, &cur, level, &childHash, 1);
758+
if( rc==SQLITE_OK ){
759+
pMut->newRoot = childHash;
760+
}
761+
prollyCursorClose(&cur);
762+
return rc;
810763
}
811-
prollyCursorClose(&cur);
812-
return rc;
813764
}
814765

815-
static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
766+
static int tryDeleteSingleNoRechunk(ProllyMutator *pMut){
816767
ProllyMutMapEntry *pEdit;
817768
ProllyCursor cur;
818769
ProllyHash childHash;
819-
i64 iKey = 0;
770+
i64 iKey;
820771
int rc;
821772
int res = 0;
822773
int level;
@@ -825,7 +776,7 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
825776
if( prollyMutMapCount(pMut->pEdits)!=1 ) return SQLITE_NOTFOUND;
826777

827778
pEdit = &pMut->pEdits->aEntries[0];
828-
if( pEdit->op!=PROLLY_EDIT_INSERT ){
779+
if( pEdit->op!=PROLLY_EDIT_DELETE ){
829780
return SQLITE_NOTFOUND;
830781
}
831782
if( (pMut->flags & PROLLY_NODE_INTKEY) && pEdit->nKey!=8 ){
@@ -844,26 +795,11 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
844795
prollyCursorClose(&cur);
845796
return rc;
846797
}
847-
if( res==0 || cur.eState!=PROLLY_CURSOR_VALID ){
798+
if( res!=0 || cur.eState!=PROLLY_CURSOR_VALID ){
848799
prollyCursorClose(&cur);
849800
return SQLITE_NOTFOUND;
850801
}
851802

852-
if( pMut->flags & PROLLY_NODE_INTKEY ){
853-
if( iKey>=prollyCursorIntKey(&cur) ){
854-
prollyCursorClose(&cur);
855-
return SQLITE_NOTFOUND;
856-
}
857-
}else{
858-
const u8 *pCurKey;
859-
int nCurKey;
860-
prollyCursorKey(&cur, &pCurKey, &nCurKey);
861-
if( compareKeys(pEdit->pKey, pEdit->nKey, pCurKey, nCurKey)>=0 ){
862-
prollyCursorClose(&cur);
863-
return SQLITE_NOTFOUND;
864-
}
865-
}
866-
867803
level = cur.iLevel;
868804
{
869805
ProllyNode *pLeaf = &cur.aLevel[level].pEntry->node;
@@ -872,22 +808,14 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
872808
int requireBoundary;
873809
int i;
874810

875-
if( idx<0 || idx>=(int)pLeaf->nItems ){
811+
if( pLeaf->nItems<=1 || idx==(int)pLeaf->nItems - 1 ){
876812
prollyCursorClose(&cur);
877813
return SQLITE_NOTFOUND;
878814
}
879815

880816
prollyNodeBuilderInit(&b, 0, pMut->flags);
881817
for(i=0; i<(int)pLeaf->nItems; i++){
882-
if( i==idx ){
883-
rc = prollyNodeBuilderAdd(&b, pEdit->pKey, pEdit->nKey,
884-
pEdit->pVal, pEdit->nVal);
885-
if( rc!=SQLITE_OK ){
886-
prollyNodeBuilderFree(&b);
887-
prollyCursorClose(&cur);
888-
return rc;
889-
}
890-
}
818+
if( i==idx ) continue;
891819
rc = appendNodeEntryToBuilder(&b, pLeaf, i, 0);
892820
if( rc!=SQLITE_OK ){
893821
prollyNodeBuilderFree(&b);
@@ -905,7 +833,7 @@ static int tryInsertSingleNoRechunk(ProllyMutator *pMut){
905833
}
906834
}
907835

908-
rc = rewriteAncestorSpine(pMut, &cur, level, &childHash, 1);
836+
rc = rewriteAncestorSpine(pMut, &cur, level, &childHash, -1);
909837
if( rc==SQLITE_OK ){
910838
pMut->newRoot = childHash;
911839
}
@@ -1136,16 +1064,13 @@ int prollyMutateFlush(ProllyMutator *pMut){
11361064
if( prollyHashIsEmpty(&pMut->oldRoot) ){
11371065
rc = buildFromEdits(pMut);
11381066
}else{
1139-
rc = tryReplaceSingleSameSize(pMut);
1067+
rc = tryInsertOrReplaceSingleNoRechunk(pMut);
11401068
if( rc==SQLITE_NOTFOUND ){
11411069
rc = tryAppendSingleIntNoSplit(pMut);
11421070
}
11431071
if( rc==SQLITE_NOTFOUND ){
11441072
rc = tryDeleteSingleNoRechunk(pMut);
11451073
}
1146-
if( rc==SQLITE_NOTFOUND ){
1147-
rc = tryInsertSingleNoRechunk(pMut);
1148-
}
11491074
if( rc==SQLITE_NOTFOUND ){
11501075
rc = streamingMerge(pMut);
11511076
}

0 commit comments

Comments
 (0)