Commit d480d28f authored by Marko Mäkelä's avatar Marko Mäkelä

Add page_has_prev(), page_has_next(), page_has_siblings()

Until now, InnoDB inefficiently compared the aligned fields
FIL_PAGE_PREV, FIL_PAGE_NEXT to the byte-order-agnostic value FIL_NULL.

This is a backport of 32170f8c
from MariaDB Server 10.3.
parent 27664ef2
...@@ -1987,7 +1987,7 @@ btr_root_raise_and_insert( ...@@ -1987,7 +1987,7 @@ btr_root_raise_and_insert(
they should already have been set. The previous node field they should already have been set. The previous node field
must be FIL_NULL if root_page_zip != NULL, because the must be FIL_NULL if root_page_zip != NULL, because the
REC_INFO_MIN_REC_FLAG (of the first user record) will be REC_INFO_MIN_REC_FLAG (of the first user record) will be
set if and only if btr_page_get_prev() == FIL_NULL. */ set if and only if !page_has_prev(). */
btr_page_set_next(root, root_page_zip, FIL_NULL, mtr); btr_page_set_next(root, root_page_zip, FIL_NULL, mtr);
btr_page_set_prev(root, root_page_zip, FIL_NULL, mtr); btr_page_set_prev(root, root_page_zip, FIL_NULL, mtr);
...@@ -3361,8 +3361,7 @@ btr_lift_page_up( ...@@ -3361,8 +3361,7 @@ btr_lift_page_up(
bool lift_father_up; bool lift_father_up;
buf_block_t* block_orig = block; buf_block_t* block_orig = block;
ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); ut_ad(!page_has_siblings(page));
ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_is_block_fix(mtr, block, MTR_MEMO_PAGE_X_FIX, index->table)); ut_ad(mtr_is_block_fix(mtr, block, MTR_MEMO_PAGE_X_FIX, index->table));
page_level = btr_page_get_level(page, mtr); page_level = btr_page_get_level(page, mtr);
...@@ -3429,8 +3428,7 @@ btr_lift_page_up( ...@@ -3429,8 +3428,7 @@ btr_lift_page_up(
page = buf_block_get_frame(block); page = buf_block_get_frame(block);
page_level = btr_page_get_level(page, mtr); page_level = btr_page_get_level(page, mtr);
ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); ut_ad(!page_has_siblings(page));
ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_is_block_fix( ut_ad(mtr_is_block_fix(
mtr, block, MTR_MEMO_PAGE_X_FIX, index->table)); mtr, block, MTR_MEMO_PAGE_X_FIX, index->table));
...@@ -5077,13 +5075,13 @@ btr_validate_level( ...@@ -5077,13 +5075,13 @@ btr_validate_level(
if (left_page_no == FIL_NULL) { if (left_page_no == FIL_NULL) {
ut_a(node_ptr == page_rec_get_next( ut_a(node_ptr == page_rec_get_next(
page_get_infimum_rec(father_page))); page_get_infimum_rec(father_page)));
ut_a(btr_page_get_prev(father_page, &mtr) == FIL_NULL); ut_a(!page_has_prev(father_page));
} }
if (right_page_no == FIL_NULL) { if (right_page_no == FIL_NULL) {
ut_a(node_ptr == page_rec_get_prev( ut_a(node_ptr == page_rec_get_prev(
page_get_supremum_rec(father_page))); page_get_supremum_rec(father_page)));
ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL); ut_a(!page_has_next(father_page));
} else { } else {
const rec_t* right_node_ptr; const rec_t* right_node_ptr;
......
...@@ -595,10 +595,10 @@ btr_cur_will_modify_tree( ...@@ -595,10 +595,10 @@ btr_cur_will_modify_tree(
/* is first, 2nd or last record */ /* is first, 2nd or last record */
if (page_rec_is_first(rec, page) if (page_rec_is_first(rec, page)
|| (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL || (page_has_next(page)
&& (page_rec_is_last(rec, page) && (page_rec_is_last(rec, page)
|| page_rec_is_second_last(rec, page))) || page_rec_is_second_last(rec, page)))
|| (mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL || (page_has_prev(page)
&& page_rec_is_second(rec, page))) { && page_rec_is_second(rec, page))) {
return(true); return(true);
} }
...@@ -680,13 +680,10 @@ btr_cur_need_opposite_intention( ...@@ -680,13 +680,10 @@ btr_cur_need_opposite_intention(
{ {
switch (lock_intention) { switch (lock_intention) {
case BTR_INTENTION_DELETE: case BTR_INTENTION_DELETE:
return((mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL return (page_has_prev(page) && page_rec_is_first(rec, page)) ||
&& page_rec_is_first(rec, page)) (page_has_next(page) && page_rec_is_last(rec, page));
|| (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL
&& page_rec_is_last(rec, page)));
case BTR_INTENTION_INSERT: case BTR_INTENTION_INSERT:
return(mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL return page_has_next(page) && page_rec_is_last(rec, page);
&& page_rec_is_last(rec, page));
case BTR_INTENTION_BOTH: case BTR_INTENTION_BOTH:
return(false); return(false);
} }
...@@ -1898,7 +1895,7 @@ btr_cur_search_to_nth_level( ...@@ -1898,7 +1895,7 @@ btr_cur_search_to_nth_level(
MTR_MEMO_PAGE_S_FIX MTR_MEMO_PAGE_S_FIX
| MTR_MEMO_PAGE_X_FIX)); | MTR_MEMO_PAGE_X_FIX));
if (btr_page_get_prev(page, mtr) != FIL_NULL if (page_has_prev(page)
&& page_rec_is_first(node_ptr, page)) { && page_rec_is_first(node_ptr, page)) {
if (leftmost_from_level == 0) { if (leftmost_from_level == 0) {
...@@ -2015,7 +2012,7 @@ btr_cur_search_to_nth_level( ...@@ -2015,7 +2012,7 @@ btr_cur_search_to_nth_level(
} else if (!dict_index_is_spatial(index) } else if (!dict_index_is_spatial(index)
&& latch_mode == BTR_MODIFY_TREE && latch_mode == BTR_MODIFY_TREE
&& lock_intention == BTR_INTENTION_INSERT && lock_intention == BTR_INTENTION_INSERT
&& mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL && page_has_next(page)
&& page_rec_is_last(page_cur_get_rec(page_cursor), page)) { && page_rec_is_last(page_cur_get_rec(page_cursor), page)) {
/* btr_insert_into_right_sibling() might cause /* btr_insert_into_right_sibling() might cause
...@@ -5302,7 +5299,7 @@ btr_cur_pessimistic_delete( ...@@ -5302,7 +5299,7 @@ btr_cur_pessimistic_delete(
} else if (UNIV_UNLIKELY(page_rec_is_first(rec, page))) { } else if (UNIV_UNLIKELY(page_rec_is_first(rec, page))) {
rec_t* next_rec = page_rec_get_next(rec); rec_t* next_rec = page_rec_get_next(rec);
if (btr_page_get_prev(page, mtr) == FIL_NULL) { if (!page_has_prev(page)) {
/* If we delete the leftmost node pointer on a /* If we delete the leftmost node pointer on a
non-leaf level, we must mark the new leftmost node non-leaf level, we must mark the new leftmost node
...@@ -6325,7 +6322,8 @@ btr_estimate_number_of_different_key_vals( ...@@ -6325,7 +6322,8 @@ btr_estimate_number_of_different_key_vals(
} }
} }
if (n_cols == dict_index_get_n_unique_in_tree(index)) { if (n_cols == dict_index_get_n_unique_in_tree(index)
&& page_has_siblings(page)) {
/* If there is more than one leaf page in the tree, /* If there is more than one leaf page in the tree,
we add one because we know that the first record we add one because we know that the first record
...@@ -6336,12 +6334,8 @@ btr_estimate_number_of_different_key_vals( ...@@ -6336,12 +6334,8 @@ btr_estimate_number_of_different_key_vals(
algorithm grossly underestimated the number of rows algorithm grossly underestimated the number of rows
in the table. */ in the table. */
if (btr_page_get_prev(page, &mtr) != FIL_NULL
|| btr_page_get_next(page, &mtr) != FIL_NULL) {
n_diff[n_cols - 1]++; n_diff[n_cols - 1]++;
} }
}
mtr_commit(&mtr); mtr_commit(&mtr);
} }
......
...@@ -602,7 +602,7 @@ btr_defragment_n_pages( ...@@ -602,7 +602,7 @@ btr_defragment_n_pages(
} }
if (n_pages == 1) { if (n_pages == 1) {
if (btr_page_get_prev(first_page, mtr) == FIL_NULL) { if (!page_has_prev(first_page)) {
/* last page in the index */ /* last page in the index */
if (dict_index_get_page(index) if (dict_index_get_page(index)
== page_get_page_no(first_page)) == page_get_page_no(first_page))
......
...@@ -1076,7 +1076,7 @@ dict_stats_analyze_index_level( ...@@ -1076,7 +1076,7 @@ dict_stats_analyze_index_level(
ut_a(btr_page_get_level(page, mtr) == level); ut_a(btr_page_get_level(page, mtr) == level);
/* there should not be any pages on the left */ /* there should not be any pages on the left */
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); ut_a(!page_has_prev(page));
/* check whether the first record on the leftmost page is marked /* check whether the first record on the leftmost page is marked
as such, if we are on a non-leaf level */ as such, if we are on a non-leaf level */
...@@ -1689,7 +1689,7 @@ dict_stats_analyze_index_for_n_prefix( ...@@ -1689,7 +1689,7 @@ dict_stats_analyze_index_for_n_prefix(
ut_a(btr_page_get_level(page, mtr) == n_diff_data->level); ut_a(btr_page_get_level(page, mtr) == n_diff_data->level);
/* there should not be any pages on the left */ /* there should not be any pages on the left */
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); ut_a(!page_has_prev(page));
/* check whether the first record on the leftmost page is marked /* check whether the first record on the leftmost page is marked
as such; we are on a non-leaf level */ as such; we are on a non-leaf level */
......
...@@ -1063,7 +1063,7 @@ rtr_page_split_and_insert( ...@@ -1063,7 +1063,7 @@ rtr_page_split_and_insert(
page_no = block->page.id.page_no(); page_no = block->page.id.page_no();
if (btr_page_get_prev(page, mtr) == FIL_NULL && !page_is_leaf(page)) { if (!page_has_prev(page) && !page_is_leaf(page)) {
first_rec = page_rec_get_next( first_rec = page_rec_get_next(
page_get_infimum_rec(buf_block_get_frame(block))); page_get_infimum_rec(buf_block_get_frame(block)));
} }
......
...@@ -1713,7 +1713,7 @@ rtr_cur_search_with_match( ...@@ -1713,7 +1713,7 @@ rtr_cur_search_with_match(
first page as much as possible, as there will be problem first page as much as possible, as there will be problem
when update MIN_REC rec in compress table */ when update MIN_REC rec in compress table */
if (buf_block_get_page_zip(block) if (buf_block_get_page_zip(block)
&& mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL && !page_has_prev(page)
&& page_get_n_recs(page) >= 2) { && page_get_n_recs(page) >= 2) {
rec = page_rec_get_next_const(rec); rec = page_rec_get_next_const(rec);
......
...@@ -3254,8 +3254,7 @@ ibuf_get_entry_counter_func( ...@@ -3254,8 +3254,7 @@ ibuf_get_entry_counter_func(
return(ULINT_UNDEFINED); return(ULINT_UNDEFINED);
} else if (!page_rec_is_infimum(rec)) { } else if (!page_rec_is_infimum(rec)) {
return(ibuf_get_entry_counter_low(mtr, rec, space, page_no)); return(ibuf_get_entry_counter_low(mtr, rec, space, page_no));
} else if (only_leaf } else if (only_leaf || !page_has_prev(page_align(rec))) {
|| fil_page_get_prev(page_align(rec)) == FIL_NULL) {
/* The parent node pointer did not contain the /* The parent node pointer did not contain the
searched for (space, page_no), which means that the searched for (space, page_no), which means that the
search ended on the correct page regardless of the search ended on the correct page regardless of the
......
...@@ -138,10 +138,9 @@ btr_cur_compress_recommendation( ...@@ -138,10 +138,9 @@ btr_cur_compress_recommendation(
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2U, LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2U,
return(FALSE)); return(FALSE));
if ((page_get_data_size(page) if (page_get_data_size(page)
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)
|| ((btr_page_get_next(page, mtr) == FIL_NULL) || !page_has_siblings(page)) {
&& (btr_page_get_prev(page, mtr) == FIL_NULL))) {
/* The page fillfactor has dropped below a predefined /* The page fillfactor has dropped below a predefined
minimum value OR the level in the B-tree contains just minimum value OR the level in the B-tree contains just
...@@ -174,11 +173,9 @@ btr_cur_can_delete_without_compress( ...@@ -174,11 +173,9 @@ btr_cur_can_delete_without_compress(
page = btr_cur_get_page(cursor); page = btr_cur_get_page(cursor);
if ((page_get_data_size(page) - rec_size if (page_get_data_size(page) - rec_size
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)
|| ((btr_page_get_next(page, mtr) == FIL_NULL) || !page_has_siblings(page) || page_get_n_recs(page) < 2) {
&& (btr_page_get_prev(page, mtr) == FIL_NULL))
|| (page_get_n_recs(page) < 2)) {
/* The page fillfactor will drop below a predefined /* The page fillfactor will drop below a predefined
minimum value, OR the level in the B-tree contains just minimum value, OR the level in the B-tree contains just
......
...@@ -219,12 +219,8 @@ btr_pcur_is_before_first_in_tree( ...@@ -219,12 +219,8 @@ btr_pcur_is_before_first_in_tree(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) { return !page_has_prev(btr_pcur_get_page(cursor))
&& page_cur_is_before_first(btr_pcur_get_page_cur(cursor));
return(FALSE);
}
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
} }
/*********************************************************//** /*********************************************************//**
...@@ -240,12 +236,8 @@ btr_pcur_is_after_last_in_tree( ...@@ -240,12 +236,8 @@ btr_pcur_is_after_last_in_tree(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) { return !page_has_next(btr_pcur_get_page(cursor))
&& page_cur_is_after_last(btr_pcur_get_page_cur(cursor));
return(FALSE);
}
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
} }
/*********************************************************//** /*********************************************************//**
......
...@@ -697,6 +697,24 @@ inline bool page_has_siblings(const page_t* page) ...@@ -697,6 +697,24 @@ inline bool page_has_siblings(const page_t* page)
!= ~uint64_t(0); != ~uint64_t(0);
} }
/** Determine whether a page has a predecessor.
@param[in] page page frame
@return true if the page has a predecessor */
inline bool page_has_prev(const page_t* page)
{
return *reinterpret_cast<const uint32_t*>(page + FIL_PAGE_PREV)
!= FIL_NULL;
}
/** Determine whether a page has a successor.
@param[in] page page frame
@return true if the page has a successor */
inline bool page_has_next(const page_t* page)
{
return *reinterpret_cast<const uint32_t*>(page + FIL_PAGE_NEXT)
!= FIL_NULL;
}
/************************************************************//** /************************************************************//**
Gets the pointer to the next record on the page. Gets the pointer to the next record on the page.
@return pointer to next record */ @return pointer to next record */
......
...@@ -521,7 +521,7 @@ page_cur_search_with_match( ...@@ -521,7 +521,7 @@ page_cur_search_with_match(
ulint rec_info = rec_get_info_bits(mid_rec, ulint rec_info = rec_get_info_bits(mid_rec,
rec_offs_comp(offsets)); rec_offs_comp(offsets));
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG); ut_ad(rec_info & REC_INFO_MIN_REC_FLAG);
ut_ad(btr_page_get_prev(page, &mtr) == FIL_NULL); ut_ad(!page_has_prev(page));
mtr_commit(&mtr); mtr_commit(&mtr);
#endif #endif
......
...@@ -2764,8 +2764,7 @@ page_delete_rec( ...@@ -2764,8 +2764,7 @@ page_delete_rec(
if (!rec_offs_any_extern(offsets) if (!rec_offs_any_extern(offsets)
&& ((page_get_data_size(page) - rec_offs_size(offsets) && ((page_get_data_size(page) - rec_offs_size(offsets)
< BTR_CUR_PAGE_COMPRESS_LIMIT(index)) < BTR_CUR_PAGE_COMPRESS_LIMIT(index))
|| (mach_read_from_4(page + FIL_PAGE_NEXT) == FIL_NULL || !page_has_siblings(page)
&& mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL)
|| (page_get_n_recs(page) < 2))) { || (page_get_n_recs(page) < 2))) {
ulint root_page_no = dict_index_get_page(index); ulint root_page_no = dict_index_get_page(index);
......
...@@ -670,8 +670,7 @@ page_zip_dir_encode( ...@@ -670,8 +670,7 @@ page_zip_dir_encode(
status = REC_STATUS_ORDINARY; status = REC_STATUS_ORDINARY;
} else { } else {
status = REC_STATUS_NODE_PTR; status = REC_STATUS_NODE_PTR;
if (UNIV_UNLIKELY if (UNIV_UNLIKELY(!page_has_prev(page))) {
(mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL)) {
min_mark = REC_INFO_MIN_REC_FLAG; min_mark = REC_INFO_MIN_REC_FLAG;
} }
} }
...@@ -3187,8 +3186,7 @@ page_zip_decompress_low( ...@@ -3187,8 +3186,7 @@ page_zip_decompress_low(
goto err_exit; goto err_exit;
} }
info_bits = mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL info_bits = page_has_prev(page) ? 0 : REC_INFO_MIN_REC_FLAG;
? REC_INFO_MIN_REC_FLAG : 0;
if (UNIV_UNLIKELY(!page_zip_set_extra_bytes(page_zip, page, if (UNIV_UNLIKELY(!page_zip_set_extra_bytes(page_zip, page,
info_bits))) { info_bits))) {
...@@ -4826,9 +4824,8 @@ page_zip_copy_recs( ...@@ -4826,9 +4824,8 @@ page_zip_copy_recs(
+ page_zip->m_end < page_zip_get_size(page_zip)); + page_zip->m_end < page_zip_get_size(page_zip));
if (!page_is_leaf(src) if (!page_is_leaf(src)
&& UNIV_UNLIKELY(mach_read_from_4(src + FIL_PAGE_PREV) == FIL_NULL) && UNIV_UNLIKELY(!page_has_prev(src))
&& UNIV_LIKELY(mach_read_from_4(page && UNIV_LIKELY(page_has_prev(page))) {
+ FIL_PAGE_PREV) != FIL_NULL)) {
/* Clear the REC_INFO_MIN_REC_FLAG of the first user record. */ /* Clear the REC_INFO_MIN_REC_FLAG of the first user record. */
ulint offs = rec_get_next_offs(page + PAGE_NEW_INFIMUM, ulint offs = rec_get_next_offs(page + PAGE_NEW_INFIMUM,
TRUE); TRUE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment