496
548
/* Loop and search until we arrive at the desired level */
504
zip_size = dict_table_zip_size(index->table);
505
rw_latch = RW_NO_LATCH;
508
if (height == 0 && latch_mode <= BTR_MODIFY_LEAF) {
510
rw_latch = latch_mode;
513
&& ibuf_should_try(index, ignore_sec_unique)) {
515
/* Try insert to the insert buffer if the
516
page is not in the buffer pool */
518
buf_mode = BUF_GET_IF_IN_POOL;
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;
571
zip_size = dict_table_zip_size(index->table);
523
block = buf_page_get_gen(space, zip_size, page_no,
524
rw_latch, guess, buf_mode,
527
/* This must be a search to perform an insert;
528
try insert to the insert buffer */
530
ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
531
ut_ad(insert_planned);
534
if (ibuf_insert(tuple, index, space, zip_size,
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:
588
ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
590
if (ibuf_insert(IBUF_OP_INSERT, tuple, index,
591
space, zip_size, page_no,
594
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,
535
605
page_no, cursor->thr)) {
536
/* Insertion to the insert buffer succeeded */
537
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
538
if (UNIV_LIKELY_NULL(heap)) {
607
cursor->flag = BTR_CUR_DEL_MARK_IBUF;
544
/* Insert to the insert buffer did not succeed:
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);
547
747
buf_mode = BUF_GET;
748
rw_latch = RW_NO_LATCH;
549
749
goto retry_page_get;
552
page = buf_block_get_frame(block);
554
block->check_index_page_at_flush = TRUE;
556
if (rw_latch != RW_NO_LATCH) {
557
#ifdef UNIV_ZIP_DEBUG
558
const page_zip_des_t* page_zip
559
= buf_block_get_page_zip(block);
560
ut_a(!page_zip || page_zip_validate(page_zip, page));
561
#endif /* UNIV_ZIP_DEBUG */
563
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
566
ut_ad(0 == ut_dulint_cmp(index->id,
567
btr_page_get_index_id(page)));
569
if (UNIV_UNLIKELY(height == ULINT_UNDEFINED)) {
570
/* We are in the root node */
572
height = btr_page_get_level(page, mtr);
573
root_height = height;
574
cursor->tree_height = root_height + 1;
576
if (block != guess) {
577
info->root_guess = block;
583
if (rw_latch == RW_NO_LATCH) {
585
btr_cur_latch_leaves(page, space, zip_size,
590
if ((latch_mode != BTR_MODIFY_TREE)
591
&& (latch_mode != BTR_CONT_MODIFY_TREE)) {
593
/* Release the tree s-latch */
595
mtr_release_s_latch_at_savepoint(
597
dict_index_get_lock(index));
603
page_cur_search_with_match(block, index, tuple, page_mode,
604
&up_match, &up_bytes,
605
&low_match, &low_bytes,
609
btr_cur_add_path_info(cursor, height, root_height);
612
/* If this is the desired level, leave the loop */
614
ut_ad(height == btr_page_get_level(
615
page_cur_get_page(page_cursor), mtr));
617
if (level == height) {
620
/* x-latch the page */
621
page = btr_page_get(space, zip_size,
622
page_no, RW_X_LATCH, mtr);
623
ut_a((ibool)!!page_is_comp(page)
624
== dict_table_is_comp(index->table));
636
node_ptr = page_cur_get_rec(page_cursor);
637
offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
638
ULINT_UNDEFINED, &heap);
639
/* Go to the child node */
640
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
643
if (UNIV_LIKELY_NULL(heap)) {
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));
648
763
cursor->low_match = low_match;
649
764
cursor->low_bytes = low_bytes;
650
765
cursor->up_match = up_match;
3057
3176
slot = cursor->path_arr + (root_height - height);
3178
page = page_align(rec);
3059
3180
slot->nth_rec = page_rec_get_n_recs_before(rec);
3060
slot->n_recs = page_get_n_recs(page_align(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 */
3063
3330
/*******************************************************************//**