Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7505da2

Browse files
Reverse order of newitem nbtree candidate splits.
Commitfab2502, which taught nbtree to choose candidate split pointsmore carefully, had _bt_findsplitloc() record all possible split pointsin an initial pass over a page that is about to be split. The orderthat candidate split points were processed and stored in was assumed tomatch the offset number order of split points on an imaginary version ofthe page that contains the same items as the original, but also fitsnewitem (the item that provoked the split precisely because it didn'tfit).However, the order of split points in the final array was not quite whatwas expected: the split point that makes newitem the firstright itemcame after the split point that makes newitem the lastleft item -- notbefore. As a result, _bt_findsplitloc() could get confused about theleftmost and rightmost tuples among all possible split points recordedfor the page. This seems to have no appreciable impact on the qualityof the final split point chosen by _bt_findsplitloc(), but it's stillwrong.To fix, switch the order in which newitem candidate splits are recordedin. This also makes it possible to describe candidate split points interms of which pair of adjoining tuples enclose the split point within_bt_findsplitloc(), making it clearer why it's generally safe for_bt_split() to expect lastleft and firstright tuples.
1 parenta429164 commit7505da2

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

‎src/backend/access/nbtree/nbtsplitloc.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,7 @@ _bt_findsplitloc(Relation rel,
196196

197197
/*
198198
* Scan through the data items and calculate space usage for a split at
199-
* each possible position. We start at the first data offset rather than
200-
* the second data offset to handle the "newitemoff == first data offset"
201-
* case (any other split whose firstoldonright is the first data offset
202-
* can't be legal, though, and so won't actually end up being recorded in
203-
* first loop iteration).
199+
* each possible position
204200
*/
205201
olddataitemstoleft=0;
206202

@@ -214,27 +210,38 @@ _bt_findsplitloc(Relation rel,
214210
itemsz=MAXALIGN(ItemIdGetLength(itemid))+sizeof(ItemIdData);
215211

216212
/*
217-
* Will the new item go to left or right of split?
213+
* When item offset number is not newitemoff, neither side of the
214+
* split can be newitem. Record a split after the previous data item
215+
* from original page, but before the current data item from original
216+
* page. (_bt_recsplitloc() will reject the split when there are no
217+
* previous data items, which we rely on.)
218218
*/
219-
if (offnum>newitemoff)
220-
_bt_recsplitloc(&state,offnum, true,olddataitemstoleft,itemsz);
221-
elseif (offnum<newitemoff)
219+
if (offnum<newitemoff)
222220
_bt_recsplitloc(&state,offnum, false,olddataitemstoleft,itemsz);
221+
elseif (offnum>newitemoff)
222+
_bt_recsplitloc(&state,offnum, true,olddataitemstoleft,itemsz);
223223
else
224224
{
225-
/* may need to record a split on one or both sides of new item */
226-
_bt_recsplitloc(&state,offnum, true,olddataitemstoleft,itemsz);
225+
/*
226+
* Record a split after all "offnum < newitemoff" original page
227+
* data items, but before newitem
228+
*/
227229
_bt_recsplitloc(&state,offnum, false,olddataitemstoleft,itemsz);
230+
231+
/*
232+
* Record a split after newitem, but before data item from
233+
* original page at offset newitemoff/current offset
234+
*/
235+
_bt_recsplitloc(&state,offnum, true,olddataitemstoleft,itemsz);
228236
}
229237

230238
olddataitemstoleft+=itemsz;
231239
}
232240

233241
/*
234-
* If the new item goes as the last item, record the split point that
235-
* leaves all the old items on the left page, and the new item on the
236-
* right page. This is required because a split that leaves the new item
237-
* as the firstoldonright won't have been reached within the loop.
242+
* Record a split after all original page data items, but before newitem.
243+
* (Though only when it's possible that newitem will end up alone on new
244+
* right page.)
238245
*/
239246
Assert(olddataitemstoleft==olddataitemstotal);
240247
if (newitemoff>maxoff)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp