548
494
/* Loop and search until we arrive at the desired level */
552
rw_latch = RW_NO_LATCH;
555
/* We are about to fetch the root or a non-leaf page. */
556
} else if (latch_mode <= BTR_MODIFY_LEAF) {
557
rw_latch = latch_mode;
559
if (btr_op != BTR_NO_OP
560
&& ibuf_should_try(index, btr_op != BTR_INSERT_OP)) {
562
/* Try to buffer the operation if the leaf
563
page is not in the buffer pool. */
565
buf_mode = btr_op == BTR_DELETE_OP
566
? BUF_GET_IF_IN_POOL_OR_WATCH
567
: BUF_GET_IF_IN_POOL;
502
zip_size = dict_table_zip_size(index->table);
503
rw_latch = RW_NO_LATCH;
506
if (height == 0 && latch_mode <= BTR_MODIFY_LEAF) {
508
rw_latch = latch_mode;
511
&& ibuf_should_try(index, ignore_sec_unique)) {
513
/* Try insert to the insert buffer if the
514
page is not in the buffer pool */
516
buf_mode = BUF_GET_IF_IN_POOL;
571
zip_size = dict_table_zip_size(index->table);
574
block = buf_page_get_gen(
575
space, zip_size, page_no, rw_latch, guess, buf_mode,
579
/* This must be a search to perform an insert/delete
580
mark/ delete; try using the insert/delete buffer */
587
case BTR_INSERT_IGNORE_UNIQUE_OP:
521
block = buf_page_get_gen(space, zip_size, page_no,
522
rw_latch, guess, buf_mode,
523
__FILE__, __LINE__, mtr);
525
/* This must be a search to perform an insert;
526
try insert to the insert buffer */
588
528
ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
590
if (ibuf_insert(IBUF_OP_INSERT, tuple, index,
591
space, zip_size, page_no,
529
ut_ad(insert_planned);
532
if (ibuf_insert(tuple, index, space, zip_size,
533
page_no, cursor->thr)) {
534
/* Insertion to the insert buffer succeeded */
594
535
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
601
ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
603
if (ibuf_insert(IBUF_OP_DELETE_MARK, tuple,
604
index, space, zip_size,
605
page_no, cursor->thr)) {
607
cursor->flag = BTR_CUR_DEL_MARK_IBUF;
615
ut_ad(buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH);
617
if (!row_purge_poss_sec(cursor->purge_node,
620
/* The record cannot be purged yet. */
621
cursor->flag = BTR_CUR_DELETE_REF;
622
} else if (ibuf_insert(IBUF_OP_DELETE, tuple,
623
index, space, zip_size,
627
/* The purge was buffered. */
628
cursor->flag = BTR_CUR_DELETE_IBUF;
630
/* The purge could not be buffered. */
631
buf_pool_watch_unset(space, page_no);
635
buf_pool_watch_unset(space, page_no);
642
/* Insert to the insert/delete buffer did not succeed, we
643
must read the page from disk. */
650
block->check_index_page_at_flush = TRUE;
651
page = buf_block_get_frame(block);
653
if (rw_latch != RW_NO_LATCH) {
654
#ifdef UNIV_ZIP_DEBUG
655
const page_zip_des_t* page_zip
656
= buf_block_get_page_zip(block);
657
ut_a(!page_zip || page_zip_validate(page_zip, page));
658
#endif /* UNIV_ZIP_DEBUG */
660
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
663
ut_ad(index->id == btr_page_get_index_id(page));
665
if (UNIV_UNLIKELY(height == ULINT_UNDEFINED)) {
666
/* We are in the root node */
668
height = btr_page_get_level(page, mtr);
669
root_height = height;
670
cursor->tree_height = root_height + 1;
673
if (block != guess) {
674
info->root_guess = block;
680
if (rw_latch == RW_NO_LATCH) {
682
btr_cur_latch_leaves(
683
page, space, zip_size, page_no, latch_mode,
687
if (latch_mode != BTR_MODIFY_TREE
688
&& latch_mode != BTR_CONT_MODIFY_TREE) {
690
/* Release the tree s-latch */
692
mtr_release_s_latch_at_savepoint(
693
mtr, savepoint, dict_index_get_lock(index));
699
page_cur_search_with_match(
700
block, index, tuple, page_mode, &up_match, &up_bytes,
701
&low_match, &low_bytes, page_cursor);
704
btr_cur_add_path_info(cursor, height, root_height);
707
/* If this is the desired level, leave the loop */
709
ut_ad(height == btr_page_get_level(page_cur_get_page(page_cursor),
712
if (level != height) {
714
const rec_t* node_ptr;
720
node_ptr = page_cur_get_rec(page_cursor);
722
offsets = rec_get_offsets(
723
node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
725
/* Go to the child node */
726
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
728
if (UNIV_UNLIKELY(height == 0 && dict_index_is_ibuf(index))) {
729
/* We're doing a search on an ibuf tree and we're one
730
level above the leaf page. */
736
is_min_rec = rec_get_info_bits(node_ptr, 0)
737
& REC_INFO_MIN_REC_FLAG;
741
= ibuf_rec_get_counter(node_ptr);
743
ut_a(cursor->ibuf_cnt <= 0xFFFF
744
|| cursor->ibuf_cnt == ULINT_UNDEFINED);
536
if (UNIV_LIKELY_NULL(heap)) {
542
/* Insert to the insert buffer did not succeed:
747
545
buf_mode = BUF_GET;
748
rw_latch = RW_NO_LATCH;
749
547
goto retry_page_get;
756
/* x-latch the page */
758
space, zip_size, page_no, RW_X_LATCH, mtr);
760
ut_a((ibool)!!page_is_comp(page)
761
== dict_table_is_comp(index->table));
550
page = buf_block_get_frame(block);
552
block->check_index_page_at_flush = TRUE;
554
if (rw_latch != RW_NO_LATCH) {
555
#ifdef UNIV_ZIP_DEBUG
556
const page_zip_des_t* page_zip
557
= buf_block_get_page_zip(block);
558
ut_a(!page_zip || page_zip_validate(page_zip, page));
559
#endif /* UNIV_ZIP_DEBUG */
561
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
564
ut_ad(0 == ut_dulint_cmp(index->id,
565
btr_page_get_index_id(page)));
567
if (UNIV_UNLIKELY(height == ULINT_UNDEFINED)) {
568
/* We are in the root node */
570
height = btr_page_get_level(page, mtr);
571
root_height = height;
572
cursor->tree_height = root_height + 1;
574
if (block != guess) {
575
info->root_guess = block;
581
if (rw_latch == RW_NO_LATCH) {
583
btr_cur_latch_leaves(page, space, zip_size,
588
if ((latch_mode != BTR_MODIFY_TREE)
589
&& (latch_mode != BTR_CONT_MODIFY_TREE)) {
591
/* Release the tree s-latch */
593
mtr_release_s_latch_at_savepoint(
595
dict_index_get_lock(index));
601
page_cur_search_with_match(block, index, tuple, page_mode,
602
&up_match, &up_bytes,
603
&low_match, &low_bytes,
607
btr_cur_add_path_info(cursor, height, root_height);
610
/* If this is the desired level, leave the loop */
612
ut_ad(height == btr_page_get_level(
613
page_cur_get_page(page_cursor), mtr));
615
if (level == height) {
618
/* x-latch the page */
619
page = btr_page_get(space, zip_size,
620
page_no, RW_X_LATCH, mtr);
621
ut_a((ibool)!!page_is_comp(page)
622
== dict_table_is_comp(index->table));
634
node_ptr = page_cur_get_rec(page_cursor);
635
offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
636
ULINT_UNDEFINED, &heap);
637
/* Go to the child node */
638
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
641
if (UNIV_LIKELY_NULL(heap)) {
763
646
cursor->low_match = low_match;
764
647
cursor->low_bytes = low_bytes;
765
648
cursor->up_match = up_match;
3176
3064
slot = cursor->path_arr + (root_height - height);
3178
page = page_align(rec);
3180
3066
slot->nth_rec = page_rec_get_n_recs_before(rec);
3181
slot->n_recs = page_get_n_recs(page);
3182
slot->page_no = page_get_page_no(page);
3183
slot->page_level = btr_page_get_level_low(page);
3186
/*******************************************************************//**
3187
Estimate the number of rows between slot1 and slot2 for any level on a
3188
B-tree. This function starts from slot1->page and reads a few pages to
3189
the right, counting their records. If we reach slot2->page quickly then
3190
we know exactly how many records there are between slot1 and slot2 and
3191
we set is_n_rows_exact to TRUE. If we cannot reach slot2->page quickly
3192
then we calculate the average number of records in the pages scanned
3193
so far and assume that all pages that we did not scan up to slot2->page
3194
contain the same number of records, then we multiply that average to
3195
the number of pages between slot1->page and slot2->page (which is
3196
n_rows_on_prev_level). In this case we set is_n_rows_exact to FALSE.
3197
@return number of rows (exact or estimated) */
3200
btr_estimate_n_rows_in_range_on_level(
3201
/*==================================*/
3202
dict_index_t* index, /*!< in: index */
3203
btr_path_t* slot1, /*!< in: left border */
3204
btr_path_t* slot2, /*!< in: right border */
3205
ib_int64_t n_rows_on_prev_level, /*!< in: number of rows
3206
on the previous level for the
3207
same descend paths; used to
3208
determine the numbe of pages
3210
ibool* is_n_rows_exact) /*!< out: TRUE if the returned
3211
value is exact i.e. not an
3221
space = dict_index_get_space(index);
3226
/* Assume by default that we will scan all pages between
3227
slot1->page_no and slot2->page_no */
3228
*is_n_rows_exact = TRUE;
3230
/* add records from slot1->page_no which are to the right of
3231
the record which serves as a left border of the range, if any */
3232
if (slot1->nth_rec < slot1->n_recs) {
3233
n_rows += slot1->n_recs - slot1->nth_rec;
3236
/* add records from slot2->page_no which are to the left of
3237
the record which servers as a right border of the range, if any */
3238
if (slot2->nth_rec > 1) {
3239
n_rows += slot2->nth_rec - 1;
3242
/* count the records in the pages between slot1->page_no and
3243
slot2->page_no (non inclusive), if any */
3245
zip_size = fil_space_get_zip_size(space);
3247
/* Do not read more than this number of pages in order not to hurt
3248
performance with this code which is just an estimation. If we read
3249
this many pages before reaching slot2->page_no then we estimate the
3250
average from the pages scanned so far */
3251
# define N_PAGES_READ_LIMIT 10
3253
page_no = slot1->page_no;
3254
level = slot1->page_level;
3263
/* fetch the page */
3264
block = buf_page_get(space, zip_size, page_no, RW_S_LATCH,
3267
page = buf_block_get_frame(block);
3269
/* It is possible that the tree has been reorganized in the
3270
meantime and this is a different page. If this happens the
3271
calculated estimate will be bogus, which is not fatal as
3272
this is only an estimate. We are sure that a page with
3273
page_no exists because InnoDB never frees pages, only
3275
if (fil_page_get_type(page) != FIL_PAGE_INDEX
3276
|| btr_page_get_index_id(page) != index->id
3277
|| btr_page_get_level_low(page) != level) {
3279
/* The page got reused for something else */
3286
if (page_no != slot1->page_no) {
3287
/* Do not count the records on slot1->page_no,
3288
we already counted them before this loop. */
3289
n_rows += page_get_n_recs(page);
3292
page_no = btr_page_get_next(page, &mtr);
3296
if (n_pages_read == N_PAGES_READ_LIMIT
3297
|| page_no == FIL_NULL) {
3298
/* Either we read too many pages or
3299
we reached the end of the level without passing
3300
through slot2->page_no, the tree must have changed
3305
} while (page_no != slot2->page_no);
3311
*is_n_rows_exact = FALSE;
3313
/* We did interrupt before reaching slot2->page */
3315
if (n_pages_read > 0) {
3316
/* The number of pages on this level is
3317
n_rows_on_prev_level, multiply it by the
3318
average number of recs per page so far */
3319
n_rows = n_rows_on_prev_level
3320
* n_rows / n_pages_read;
3322
/* The tree changed before we could even
3323
start with slot1->page_no */
3067
slot->n_recs = page_get_n_recs(page_align(rec));
3330
3070
/*******************************************************************//**