Commit 4a3a46af authored by unknown's avatar unknown
Browse files

InnoDB: Performance optimizations based on OProfile analysis


innobase/btr/btr0btr.c:
  Eliminate some buf_frame_align() calls.
  Make use of the page_rec_is_infimum(), page_rec_is_supremum()
  and page_rec_is_user_rec() functions.
  Replace some index->table->comp with page_is_comp().
  Eliminate some variables to reduce register spilling on x86.
  Note that page_is_comp() may return nonzero instead of TRUE.
  Note that rec_offs_comp() may return nonzero instead of TRUE.
innobase/btr/btr0cur.c:
  Eliminate some buf_frame_align() calls.
  Replace some index->table->comp with
  page_is_comp() or rec_offs_comp().
  Eliminate some variables to reduce register spilling on x86.
  Note that page_is_comp() may return nonzero instead of TRUE.
  Note that rec_offs_comp() may return nonzero instead of TRUE.
  Remove an extra mem_heap_create() call from btr_cur_update_in_place().
  Add "page" parameter to lock_rec_store_on_page_infimum().
  Add some UNIV_LIKELY() and UNIV_UNLIKELY() hints.
  
  btr_estimate_number_of_different_key_vals(): Rename the
  offsets_* variables to be more descriptive and eliminate one
  rec_get_offsets() and one page_rec_get_next() call in the loop.
innobase/btr/btr0pcur.c:
  Eliminate some buf_frame_align() calls.
  Make use of the page_rec_is_infimum(), page_rec_is_supremum()
  and page_rec_is_user_rec() functions.
  Replace some index->table->comp with page_is_comp().
  Eliminate some variables to reduce register spilling on x86.
  Note that page_is_comp() may return nonzero instead of TRUE.
  Make some ut_a() assertions ut_ad() ones to improve performance.
  Add some UNIV_LIKELY() and UNIV_UNLIKELY() hints.
innobase/btr/btr0sea.c:
  Make use of page_rec_is_infimum() and page_rec_is_supremum().
  Eliminate some buf_frame_align() calls.
  Add some UNIV_UNLIKELY and UNIV_LIKELY hints.
  Turn some assertions into debug assertions.
innobase/dict/dict0crea.c:
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp
innobase/ibuf/ibuf0ibuf.c:
  Make use of page_rec_is_infimum() and page_rec_is_supremum().
  Add some UNIV_UNLIKELY and UNIV_LIKELY hints.
  ibuf_get_merge_page_nos(): Rename parameter "first_rec" to "rec"
  and eliminate local variable "rec".
innobase/include/btr0btr.h:
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp
innobase/include/buf0buf.h:
  Rename buf_frame_get_modify_clock()
  to buf_block_get_modify_clock().
innobase/include/buf0buf.ic:
  Rename buf_frame_get_modify_clock()
  to buf_block_get_modify_clock() and
  remove the buf_block_align() call.
innobase/include/lock0lock.h:
  lock_rec_store_on_page_infimum(): Add parameter "page"
innobase/include/mach0data.h:
  Add mach_encode_2() and mach_decode_2().
innobase/include/mach0data.ic:
  Add mach_encode_2() and mach_decode_2().
innobase/include/page0cur.h:
  Add const qualifier to page_cur_is_before_first()
  and page_cur_is_after_last().
innobase/include/page0cur.ic:
  Make use of page_rec_is_infimum() and page_rec_is_supremum().
innobase/include/page0page.h:
  Remove page_rec_is_first_user_rec() and page_rec_is_last_user_rec().
  Add page_rec_is_infimum() and page_rec_is_supremum().
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
innobase/include/page0page.ic:
  Remove page_rec_is_first_user_rec() and page_rec_is_last_user_rec().
  Add page_rec_is_infimum() and page_rec_is_supremum().
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
  Add UNIV_UNLIKELY, UNIV_LIKELY and UNIV_EXPECT hints.
  Reduce the number of buf_frame_align() calls.
innobase/include/rem0rec.ic:
  rec_offs_comp(): Return zero or nonzero instead of FALSE or TRUE.
innobase/include/row0mysql.h:
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
innobase/lock/lock0lock.c:
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
  Remove parameter "comp" from lock_rec_get_next(),
  lock_rec_has_expl() and lock_rec_other_has_expl_req().
  Add parameter "page" to lock_rec_store_on_page_infimum().
  Add UNIV_UNLIKELY hints.
  Reduce the number of buf_frame_align() calls.
  Make use of page_rec_is_infimum(), page_rec_is_supremum() and
  page_rec_is_user_rec().
  Move the "comp" flag outside some loops.
innobase/mtr/mtr0log.c:
  Replace index->table->comp with page_rec_is_comp().
innobase/page/page0cur.c:
  Replace index->table->comp with page_is_comp() or page_rec_is_comp().
  Eliminate some buf_frame_align() calls.
  Add some debug assertions.
innobase/page/page0page.c:
  Optimize page_dir_find_owner_slot(). Compare the record offset
  16 bits at a time, because that seems to be the only way to avoid
  register spilling on x86.
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
  Remove parameter "page" of page_delete_rec_list_write_log().
  Make use of page_rec_is_infimum().
innobase/rem/rem0cmp.c:
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
innobase/row/row0ins.c:
  Make use of page_rec_is_infimum() and page_rec_is_supremum().
  Reduce the amount of buf_frame_align() calls.
  row_ins_index_entry_low(): Disable assertion about column count
  unless #ifdef UNIV_DEBUG.
innobase/row/row0mysql.c:
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
innobase/row/row0row.c:
  Eliminate some buf_frame_align() calls.
  Make use of page_rec_is_infimum().
innobase/row/row0sel.c:
  Make use of page_rec_is_supremum() and page_rec_is_infimum().
  Turn some assertions into debug assertions.
  Add UNIV_LIKELY and UNIV_UNLIKELY hints.
  
  row_search_for_mysql(): Eliminate local variables "moved",
  "cons_read_requires_clust_rec", "was_lock_wait", "shortcut",
  "success" and "comp". Replace some of them with goto's.
  Disable variable "cnt" unless #ifdef UNIV_SEARCH_DEBUG.
innobase/row/row0vers.c:
  Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
  Replace index->table->comp with page_rec_is_comp().
  Eliminate some buf_frame_align() calls.
parent f51eb30b
Loading
Loading
Loading
Loading
+71 −67
Original line number Diff line number Diff line
@@ -138,13 +138,13 @@ btr_root_get(
	ulint	space;
	ulint	root_page_no;
	page_t*	root;
	ibool	comp = UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp;
	
	space = dict_tree_get_space(tree);
	root_page_no = dict_tree_get_page(tree);

	root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
	ut_a(page_is_comp(root) == comp);
	ut_a(!!page_is_comp(root) ==
			UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
	
	return(root);
}
@@ -164,21 +164,19 @@ btr_get_prev_user_rec(
	page_t*	page;
	page_t*	prev_page;
	ulint	prev_page_no;
	rec_t*	prev_rec;
	ulint	space;

	page = buf_frame_align(rec);
	
	if (page_get_infimum_rec(page) != rec) {
	if (!page_rec_is_infimum(rec)) {

		prev_rec = page_rec_get_prev(rec);
		rec_t*	prev_rec = page_rec_get_prev(rec);

		if (page_get_infimum_rec(page) != prev_rec) {
		if (!page_rec_is_infimum(prev_rec)) {

			return(prev_rec);
		}
	}
	
	page = buf_frame_align(rec);
	prev_page_no = btr_page_get_prev(page, mtr);
	space = buf_frame_get_space_id(page);
	
@@ -193,9 +191,7 @@ btr_get_prev_user_rec(
		      				MTR_MEMO_PAGE_X_FIX)));
		ut_a(page_is_comp(prev_page) == page_is_comp(page));

		prev_rec = page_rec_get_prev(page_get_supremum_rec(prev_page));

		return(prev_rec);
		return(page_rec_get_prev(page_get_supremum_rec(prev_page)));
	}

	return(NULL);
@@ -216,21 +212,19 @@ btr_get_next_user_rec(
	page_t*	page;
	page_t*	next_page;
	ulint	next_page_no;
	rec_t*	next_rec;
	ulint	space;

	page = buf_frame_align(rec);
	
	if (page_get_supremum_rec(page) != rec) {
	if (!page_rec_is_supremum(rec)) {

		next_rec = page_rec_get_next(rec);
		rec_t*	next_rec = page_rec_get_next(rec);

		if (page_get_supremum_rec(page) != next_rec) {
		if (!page_rec_is_supremum(next_rec)) {

			return(next_rec);
		}
	}
	
	page = buf_frame_align(rec);
	next_page_no = btr_page_get_next(page, mtr);
	space = buf_frame_get_space_id(page);
	
@@ -245,9 +239,7 @@ btr_get_next_user_rec(
		      				MTR_MEMO_PAGE_X_FIX)));

		ut_a(page_is_comp(next_page) == page_is_comp(page));
		next_rec = page_rec_get_next(page_get_infimum_rec(next_page));

		return(next_rec);
		return(page_rec_get_next(page_get_infimum_rec(next_page)));
	}

	return(NULL);
@@ -574,8 +566,7 @@ btr_page_get_father_for_rec(

	ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
							MTR_MEMO_X_LOCK));
	ut_a(user_rec != page_get_supremum_rec(page));
	ut_a(user_rec != page_get_infimum_rec(page));
	ut_a(page_rec_is_user_rec(user_rec));
	
	ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page));

@@ -599,6 +590,7 @@ btr_page_get_father_for_rec(

	if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
                                                buf_frame_get_page_no(page)) {
		rec_t*	print_rec;
		fputs("InnoDB: Dump of the child page:\n", stderr);
		buf_page_print(buf_frame_align(page));
		fputs("InnoDB: Dump of the parent page:\n", stderr);
@@ -613,11 +605,10 @@ btr_page_get_father_for_rec(
			(ulong)
			btr_node_ptr_get_child_page_no(node_ptr, offsets),
			(ulong) buf_frame_get_page_no(page));
		offsets = rec_get_offsets(page_rec_get_next(
				page_get_infimum_rec(page)), index,
		print_rec = page_rec_get_next(page_get_infimum_rec(page));
		offsets = rec_get_offsets(print_rec, index,
				offsets, ULINT_UNDEFINED, &heap);
		page_rec_print(page_rec_get_next(page_get_infimum_rec(page)),
					offsets);
		page_rec_print(print_rec, offsets);
		offsets = rec_get_offsets(node_ptr, index, offsets,
					ULINT_UNDEFINED, &heap);
		page_rec_print(node_ptr, offsets);
@@ -664,7 +655,7 @@ btr_create(
	ulint	type,	/* in: type of the index */
	ulint	space,	/* in: space where created */
	dulint	index_id,/* in: index id */
	ibool	comp,	/* in: TRUE=compact page format */
	ulint	comp,	/* in: nonzero=compact page format */
	mtr_t*	mtr)	/* in: mini-transaction handle */
{
	ulint		page_no;
@@ -855,11 +846,12 @@ btr_page_reorganize_low(

	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
			      				MTR_MEMO_PAGE_X_FIX));
	ut_ad(!!page_is_comp(page) == index->table->comp);
	data_size1 = page_get_data_size(page);
	max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);

	/* Write the log record */
	mlog_open_and_write_index(mtr, page, index, index->table->comp
	mlog_open_and_write_index(mtr, page, index, page_is_comp(page)
			? MLOG_COMP_PAGE_REORGANIZE
			: MLOG_PAGE_REORGANIZE, 0);

@@ -878,7 +870,7 @@ btr_page_reorganize_low(
	/* Recreate the page: note that global data on page (possible
	segment headers, next page-field, etc.) is preserved intact */

	page_create(page, mtr, index->table->comp);
	page_create(page, mtr, page_is_comp(page));
	buf_block_align(page)->check_index_page_at_flush = TRUE;
	
	/* Copy the records from the temporary space to the recreated page;
@@ -1071,7 +1063,7 @@ btr_root_raise_and_insert(
	as there is no lower alphabetical limit to records in the leftmost
	node of a level: */

	btr_set_min_rec_mark(node_ptr_rec, cursor->index->table->comp, mtr);
	btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr);
		
	/* Free the memory heap */
	mem_heap_free(heap);
@@ -1152,7 +1144,6 @@ btr_page_get_split_rec_to_right(
{
	page_t*	page;
	rec_t*	insert_point;
	rec_t*	supremum;

	page = btr_cur_get_page(cursor);
	insert_point = btr_cur_get_rec(cursor);
@@ -1161,13 +1152,22 @@ btr_page_get_split_rec_to_right(
	the previous insert on the same page, we assume that there is a
	pattern of sequential inserts here. */

	if (page_header_get_ptr(page, PAGE_LAST_INSERT) == insert_point) {
	if (UNIV_LIKELY(page_header_get_ptr(page, PAGE_LAST_INSERT)
				== insert_point)) {

	     	supremum = page_get_supremum_rec(page);
		rec_t*	next_rec;

		if (page_rec_get_next(insert_point) != supremum
		    && page_rec_get_next(page_rec_get_next(insert_point))
			!= supremum) {
		next_rec = page_rec_get_next(insert_point);

		if (page_rec_is_supremum(next_rec)) {
		split_at_new:
			/* Split at the new record to insert */
	     		*split_rec = NULL;
		} else {
			rec_t*	next_next_rec = page_rec_get_next(next_rec);
			if (page_rec_is_supremum(next_next_rec)) {
				goto split_at_new;
			}

			/* If there are >= 2 user records up from the insert
			point, split all but 1 off. We want to keep one because
@@ -1176,11 +1176,7 @@ btr_page_get_split_rec_to_right(
			search position just by looking at the records on this
			page. */
		
			*split_rec = page_rec_get_next(
					page_rec_get_next(insert_point));
		} else {
			/* Else split at the new record to insert */
	     		*split_rec = NULL;
			*split_rec = next_next_rec;
		}

		return(TRUE);
@@ -1221,7 +1217,7 @@ btr_page_get_sure_split_rec(
	page = btr_cur_get_page(cursor);
	
	insert_size = rec_get_converted_size(cursor->index, tuple);
	free_space  = page_get_free_space_of_empty(cursor->index->table->comp);
	free_space  = page_get_free_space_of_empty(page_is_comp(page));

	/* free_space is now the free space of a created new page */

@@ -1283,11 +1279,8 @@ btr_page_get_sure_split_rec(
				} else {
					next_rec = page_rec_get_next(rec);
				}
				if (next_rec != page_get_supremum_rec(page)) {
					if (UNIV_LIKELY_NULL(heap)) {
						mem_heap_free(heap);
					}
					return(next_rec);
				if (!page_rec_is_supremum(next_rec))) {
					rec = next_rec;
				}
                    	}

@@ -1330,13 +1323,12 @@ btr_page_insert_fits(

	ut_ad(!split_rec == !offsets);
	ut_ad(!offsets
		|| cursor->index->table->comp == rec_offs_comp(offsets));
		|| page_is_comp(page) == !!rec_offs_comp(offsets));
	ut_ad(!offsets
		|| rec_offs_validate(split_rec, cursor->index, offsets));
	ut_ad(page_is_comp(page) == cursor->index->table->comp);

	insert_size = rec_get_converted_size(cursor->index, tuple);
	free_space  = page_get_free_space_of_empty(cursor->index->table->comp);
	free_space  = page_get_free_space_of_empty(page_is_comp(page));

	/* free_space is now the free space of a created new page */

@@ -1833,14 +1825,15 @@ void
btr_set_min_rec_mark_log(
/*=====================*/
	rec_t*	rec,	/* in: record */
	ibool	comp,	/* TRUE=compact record format */
	ulint	comp,	/* nonzero=compact record format */
	mtr_t*	mtr)	/* in: mtr */
{
	mlog_write_initial_log_record(rec,
		comp ? MLOG_COMP_REC_MIN_MARK : MLOG_REC_MIN_MARK, mtr);

	/* Write rec offset as a 2-byte ulint */
	mlog_catenate_ulint(mtr, rec - buf_frame_align(rec), MLOG_2BYTES);
	mlog_catenate_ulint(mtr, ut_align_offset(rec, UNIV_PAGE_SIZE),
								MLOG_2BYTES);
}

/********************************************************************
@@ -1853,7 +1846,7 @@ btr_parse_set_min_rec_mark(
			/* out: end of log record or NULL */
	byte*	ptr,	/* in: buffer */
	byte*	end_ptr,/* in: buffer end */
	ibool	comp,	/* in: TRUE=compact page format */
	ulint	comp,	/* in: nonzero=compact page format */
	page_t*	page,	/* in: page or NULL */
	mtr_t*	mtr)	/* in: mtr or NULL */
{
@@ -1865,6 +1858,8 @@ btr_parse_set_min_rec_mark(
	}

	if (page) {
		ut_a(!page_is_comp(page) == !comp);

		rec = page + mach_read_from_2(ptr);

		btr_set_min_rec_mark(rec, comp, mtr);
@@ -1880,7 +1875,7 @@ void
btr_set_min_rec_mark(
/*=================*/
	rec_t*	rec,	/* in: record */
	ibool	comp,	/* in: TRUE=compact page format */
	ulint	comp,	/* in: nonzero=compact page format */
	mtr_t*	mtr)	/* in: mtr */
{
	ulint	info_bits;
@@ -2009,11 +2004,12 @@ btr_compress(
	ulint		max_ins_size;
	ulint		max_ins_size_reorg;
	ulint		level;
	ibool		comp	= cursor->index->table->comp;
	ulint		comp;

	page = btr_cur_get_page(cursor);
	tree = btr_cur_get_tree(cursor);
	ut_a(comp == page_is_comp(page));
	comp = page_is_comp(page);
	ut_a(!!comp == cursor->index->table->comp);

	ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
							MTR_MEMO_X_LOCK));
@@ -2056,7 +2052,7 @@ btr_compress(
	
	n_recs = page_get_n_recs(page);
	data_size = page_get_data_size(page);
	ut_a(page_is_comp(merge_page) == page_is_comp(page));
	ut_a(page_is_comp(merge_page) == comp);

	max_ins_size_reorg = page_get_max_insert_size_after_reorganize(
							merge_page, n_recs);
@@ -2251,10 +2247,9 @@ btr_discard_page(

		node_ptr = page_rec_get_next(page_get_infimum_rec(merge_page));

		ut_ad(node_ptr != page_get_supremum_rec(merge_page));
		ut_ad(page_rec_is_user_rec(node_ptr));

		btr_set_min_rec_mark(node_ptr,
					cursor->index->table->comp, mtr);
		btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr);
	}	
	
	btr_node_ptr_delete(tree, page, mtr);
@@ -2500,7 +2495,7 @@ btr_index_rec_validate(

	page = buf_frame_align(rec);

	if (index->type & DICT_UNIVERSAL) {
	if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
	        /* The insert buffer index tree can contain records from any
	        other index: we cannot check the number of fields or
	        their length */
@@ -2508,9 +2503,18 @@ btr_index_rec_validate(
	        return(TRUE);
	}

	if (UNIV_UNLIKELY(!!page_is_comp(page) != index->table->comp)) {
		btr_index_rec_validate_report(page, rec, index);
		fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n",
			(ulong) !!page_is_comp(page),
			(ulong) index->table->comp);
		return(FALSE);
	}

	n = dict_index_get_n_fields(index);

	if (!index->table->comp && rec_get_n_fields_old(rec) != n) {
	if (!page_is_comp(page)
			&& UNIV_UNLIKELY(rec_get_n_fields_old(rec) != n)) {
		btr_index_rec_validate_report(page, rec, index);
		fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n",
			(ulong) rec_get_n_fields_old(rec), (ulong) n);
@@ -2774,7 +2778,7 @@ btr_validate_level(
	if (level > 0 && left_page_no == FIL_NULL) {
		ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
			page_rec_get_next(page_get_infimum_rec(page)),
				index->table->comp));
				page_is_comp(page)));
	}

	if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) {
@@ -2930,7 +2934,7 @@ btr_validate_level(
	mtr_commit(&mtr);

	if (right_page_no != FIL_NULL) {
		ibool	comp = page_is_comp(page);
		ulint	comp = page_is_comp(page);
		mtr_start(&mtr);
	
		page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
+91 −70
Original line number Diff line number Diff line
@@ -505,8 +505,9 @@ btr_cur_search_to_nth_level(

			if (level > 0) {
				/* x-latch the page */
				ut_a(page_is_comp(btr_page_get(space,
						page_no, RW_X_LATCH, mtr))
				page = btr_page_get(space,
						page_no, RW_X_LATCH, mtr);
				ut_a(!!page_is_comp(page)
						== index->table->comp);
			}

@@ -961,7 +962,7 @@ btr_cur_optimistic_insert(
	rec_size = rec_get_converted_size(index, entry);

	if (rec_size >=
		ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
		ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
		REC_MAX_DATA_SIZE)) {

		/* The record is so big that we have to store some fields
@@ -1027,7 +1028,7 @@ btr_cur_optimistic_insert(

	*rec = page_cur_insert_rec_low(page_cursor, entry, index,
							NULL, NULL, mtr);
	if (!(*rec)) {
	if (UNIV_UNLIKELY(!(*rec))) {
		/* If the record did not fit, reorganize */
		btr_page_reorganize(page, index, mtr);

@@ -1039,7 +1040,7 @@ btr_cur_optimistic_insert(

		*rec = page_cur_tuple_insert(page_cursor, entry, index, mtr);

		if (!*rec) {
		if (UNIV_UNLIKELY(!*rec)) {
			fputs("InnoDB: Error: cannot insert tuple ", stderr);
			dtuple_print(stderr, entry);
			fputs(" into ", stderr);
@@ -1166,7 +1167,7 @@ btr_cur_pessimistic_insert(
	}

	if (rec_get_converted_size(index, entry) >=
		ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
		ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
		REC_MAX_DATA_SIZE)) {

		/* The record is so big that we have to store some fields
@@ -1293,9 +1294,11 @@ btr_cur_update_in_place_log(
	mtr_t*		mtr)		/* in: mtr */
{
	byte*	log_ptr;
	page_t*	page	= ut_align_down(rec, UNIV_PAGE_SIZE);
	ut_ad(flags < 256);
	ut_ad(!!page_is_comp(page) == index->table->comp);

	log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
	log_ptr = mlog_open_and_write_index(mtr, rec, index, page_is_comp(page)
			? MLOG_COMP_REC_UPDATE_IN_PLACE
			: MLOG_REC_UPDATE_IN_PLACE,
			1 + DATA_ROLL_PTR_LEN + 14 + 2 + MLOG_BUF_MARGIN);
@@ -1317,7 +1320,7 @@ btr_cur_update_in_place_log(

	log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
									mtr);
	mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
	mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
	log_ptr += 2;

	row_upd_index_write_log(update, log_ptr, mtr);
@@ -1374,18 +1377,11 @@ btr_cur_parse_update_in_place(
	
	ptr = row_upd_index_parse(ptr, end_ptr, heap, &update);

	if (ptr == NULL) {
		mem_heap_free(heap);
		
		return(NULL);
	}

	if (!page) {
		mem_heap_free(heap);

		return(ptr);
	if (!ptr || !page) {
		goto func_exit;
	}

	ut_a(!!page_is_comp(page) == index->table->comp);
	rec = page + rec_offset;
	
	/* We do not need to reserve btr_search_latch, as the page is only
@@ -1400,6 +1396,7 @@ btr_cur_parse_update_in_place(

	row_upd_rec_in_place(rec, offsets, update);

func_exit:
	mem_heap_free(heap);

	return(ptr);
@@ -1438,7 +1435,6 @@ btr_cur_update_in_place(
	rec = btr_cur_get_rec(cursor);
	index = cursor->index;
	trx = thr_get_trx(thr);
	heap = mem_heap_create(100);
	offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);

	if (btr_cur_print_record_ops && thr) {
@@ -1449,7 +1445,7 @@ btr_cur_update_in_place(
	/* Do lock checking and undo logging */
	err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info,
							thr, &roll_ptr);
	if (err != DB_SUCCESS) {
	if (UNIV_UNLIKELY(err != DB_SUCCESS)) {

		if (UNIV_LIKELY_NULL(heap)) {
			mem_heap_free(heap);
@@ -1458,6 +1454,8 @@ btr_cur_update_in_place(
	}

	block = buf_block_align(rec);
	ut_ad(!!page_is_comp(buf_block_get_frame(block))
				== index->table->comp);

	if (block->is_hashed) {
		/* The function row_upd_changes_ord_field_binary works only
@@ -1481,7 +1479,8 @@ btr_cur_update_in_place(
	/* FIXME: in a mixed tree, all records may not have enough ordering
	fields for btr search: */

	was_delete_marked = rec_get_deleted_flag(rec, index->table->comp);
	was_delete_marked = rec_get_deleted_flag(rec,
				page_is_comp(buf_block_get_frame(block)));

	row_upd_rec_in_place(rec, offsets, update);

@@ -1491,7 +1490,8 @@ btr_cur_update_in_place(

	btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
									mtr);
	if (was_delete_marked && !rec_get_deleted_flag(rec, index->table->comp)) {
	if (was_delete_marked && !rec_get_deleted_flag(rec,
				page_is_comp(buf_block_get_frame(block)))) {
		/* The new updated record owns its possible externally
		stored fields */

@@ -1597,7 +1597,7 @@ btr_cur_optimistic_update(
	new_rec_size = rec_get_converted_size(index, new_entry);
	
	if (new_rec_size >=
			page_get_free_space_of_empty(index->table->comp) / 2) {
			page_get_free_space_of_empty(page_is_comp(page)) / 2) {

		mem_heap_free(heap);		

@@ -1644,7 +1644,7 @@ btr_cur_optimistic_update(
	explicit locks on rec, before deleting rec (see the comment in
	.._pessimistic_update). */

	lock_rec_store_on_page_infimum(rec);
	lock_rec_store_on_page_infimum(page, rec);

	btr_search_update_hash_on_delete(cursor);

@@ -1665,7 +1665,7 @@ btr_cur_optimistic_update(

	ut_a(rec); /* <- We calculated above the insert would fit */

	if (!rec_get_deleted_flag(rec, index->table->comp)) {
	if (!rec_get_deleted_flag(rec, page_is_comp(page))) {
		/* The new inserted record owns its possible externally
		stored fields */

@@ -1814,7 +1814,7 @@ btr_cur_pessimistic_update(
		}
		
		success = fsp_reserve_free_extents(&n_reserved,
						cursor->index->space,
						index->space,
						n_extents, reserve_flag, mtr);
		if (!success) {
			err = DB_OUT_OF_FILE_SPACE;
@@ -1858,14 +1858,14 @@ btr_cur_pessimistic_update(

	ext_vect = mem_heap_alloc(heap, sizeof(ulint)
					* dict_index_get_n_fields(index));
	ut_ad(!cursor->index->table->comp || !rec_get_node_ptr_flag(rec));
	ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
	offsets = rec_get_offsets(rec, index, offsets,
					ULINT_UNDEFINED, &heap);
	n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update);

	if (rec_get_converted_size(index, new_entry) >=
		ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
		REC_MAX_DATA_SIZE)) {
	if (UNIV_UNLIKELY(rec_get_converted_size(index, new_entry) >=
		ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
		REC_MAX_DATA_SIZE))) {

                big_rec_vec = dtuple_convert_big_rec(index, new_entry,
                					ext_vect, n_ext_vect);
@@ -1887,7 +1887,7 @@ btr_cur_pessimistic_update(
	delete the lock structs set on the root page even if the root
	page carries just node pointers. */

	lock_rec_store_on_page_infimum(rec);
	lock_rec_store_on_page_infimum(buf_frame_align(rec), rec);

	btr_search_update_hash_on_delete(cursor);

@@ -1965,8 +1965,7 @@ btr_cur_pessimistic_update(
	mem_heap_free(heap);

	if (n_extents > 0) {
		fil_space_release_free_extents(cursor->index->space,
							n_reserved);
		fil_space_release_free_extents(index->space, n_reserved);
	}

	*big_rec = big_rec_vec;
@@ -1995,7 +1994,10 @@ btr_cur_del_mark_set_clust_rec_log(
	ut_ad(flags < 256);
	ut_ad(val <= 1);

	log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
	ut_ad(!!page_rec_is_comp(rec) == index->table->comp);

	log_ptr = mlog_open_and_write_index(mtr, rec, index,
			page_rec_is_comp(rec)
			? MLOG_COMP_REC_CLUST_DELETE_MARK
			: MLOG_REC_CLUST_DELETE_MARK,
			1 + 1 + DATA_ROLL_PTR_LEN + 14 + 2);
@@ -2012,7 +2014,7 @@ btr_cur_del_mark_set_clust_rec_log(

	log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
									mtr);
	mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
	mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
	log_ptr += 2;

	mlog_close(mtr, log_ptr);
@@ -2039,6 +2041,8 @@ btr_cur_parse_del_mark_set_clust_rec(
	ulint	offset;
	rec_t*	rec;

	ut_ad(!!page_is_comp(page) == index->table->comp);

	if (end_ptr < ptr + 2) {

		return(NULL);
@@ -2087,7 +2091,7 @@ btr_cur_parse_del_mark_set_clust_rec(
		is only being recovered, and there cannot be a hash index to
		it. */

		rec_set_deleted_flag(rec, index->table->comp, val);
		rec_set_deleted_flag(rec, page_is_comp(page), val);
	}
	
	return(ptr);
@@ -2161,7 +2165,7 @@ btr_cur_del_mark_set_clust_rec(
		rw_lock_x_lock(&btr_search_latch);
	}

	rec_set_deleted_flag(rec, index->table->comp, val);
	rec_set_deleted_flag(rec, rec_offs_comp(offsets), val);

	trx = thr_get_trx(thr);
	
@@ -2486,6 +2490,7 @@ btr_cur_pessimistic_delete(
	ulint		n_reserved;
	ibool		success;
	ibool		ret		= FALSE;
	ulint		level;
	mem_heap_t*	heap;
	ulint*		offsets;
	
@@ -2522,15 +2527,15 @@ btr_cur_pessimistic_delete(
	/* Free externally stored fields if the record is neither
	a node pointer nor in two-byte format.
	This avoids an unnecessary loop. */
	if (cursor->index->table->comp
	if (page_is_comp(page)
			? !rec_get_node_ptr_flag(rec)
			: !rec_get_1byte_offs_flag(rec)) {
		btr_rec_free_externally_stored_fields(cursor->index,
					rec, offsets, in_rollback, mtr);
	}

	if ((page_get_n_recs(page) < 2)
	    && (dict_tree_get_page(btr_cur_get_tree(cursor))
	if (UNIV_UNLIKELY(page_get_n_recs(page) < 2)
	    && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor))
					!= buf_frame_get_page_no(page))) {

		/* If there is only one record, drop the whole page in
@@ -2545,9 +2550,13 @@ btr_cur_pessimistic_delete(
	}

	lock_update_delete(rec);
	level = btr_page_get_level(page, mtr);

	if ((btr_page_get_level(page, mtr) > 0)
	    && (page_rec_get_next(page_get_infimum_rec(page)) == rec)) {
	if (level > 0
	    && UNIV_UNLIKELY(rec == page_rec_get_next(
				page_get_infimum_rec(page)))) {

		rec_t*	next_rec = page_rec_get_next(rec);

		if (btr_page_get_prev(page, mtr) == FIL_NULL) {

@@ -2555,8 +2564,8 @@ btr_cur_pessimistic_delete(
			non-leaf level, we must mark the new leftmost node
			pointer as the predefined minimum record */

			btr_set_min_rec_mark(page_rec_get_next(rec),
					cursor->index->table->comp, mtr);
			btr_set_min_rec_mark(next_rec, page_is_comp(page),
						mtr);
		} else {
			/* Otherwise, if we delete the leftmost node pointer
			on a page, we have to change the father node pointer
@@ -2566,13 +2575,12 @@ btr_cur_pessimistic_delete(
			btr_node_ptr_delete(tree, page, mtr);

			node_ptr = dict_tree_build_node_ptr(
					tree, page_rec_get_next(rec),
					tree, next_rec,
					buf_frame_get_page_no(page),
       					heap, btr_page_get_level(page, mtr));
						heap, level);

			btr_insert_on_non_leaf_level(tree,
					btr_page_get_level(page, mtr) + 1,
					node_ptr, mtr);
					level + 1, node_ptr, mtr);
		}
	} 

@@ -2812,12 +2820,13 @@ btr_estimate_number_of_different_key_vals(
	ulint		add_on;
	mtr_t		mtr;
	mem_heap_t*	heap		= NULL;
	ulint		offsets1_[REC_OFFS_NORMAL_SIZE];
	ulint		offsets2_[REC_OFFS_NORMAL_SIZE];
	ulint*		offsets1	= offsets1_;
	ulint*		offsets2	= offsets2_;
	*offsets1_ = (sizeof offsets1_) / sizeof *offsets1_;
	*offsets2_ = (sizeof offsets2_) / sizeof *offsets2_;
	ulint		offsets_rec_[REC_OFFS_NORMAL_SIZE];
	ulint		offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
	ulint*		offsets_rec	= offsets_rec_;
	ulint*		offsets_next_rec= offsets_next_rec_;
	*offsets_rec_ = (sizeof offsets_rec_) / sizeof *offsets_rec_;
	*offsets_next_rec_ =
			(sizeof offsets_next_rec_) / sizeof *offsets_next_rec_;

	n_cols = dict_index_get_n_unique(index);

@@ -2830,6 +2839,7 @@ btr_estimate_number_of_different_key_vals(
	/* We sample some pages in the index to get an estimate */
	
	for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) {
		rec_t*	supremum;
		mtr_start(&mtr);

		btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
@@ -2842,26 +2852,29 @@ btr_estimate_number_of_different_key_vals(

		page = btr_cur_get_page(&cursor);

		rec = page_get_infimum_rec(page);
		rec = page_rec_get_next(rec);
		supremum = page_get_supremum_rec(page);
		rec = page_rec_get_next(page_get_infimum_rec(page));

		if (rec != page_get_supremum_rec(page)) {
		if (rec != supremum) {
			not_empty_flag = 1;
			offsets_rec = rec_get_offsets(rec, index, offsets_rec,
						ULINT_UNDEFINED, &heap);
		}

		while (rec != page_get_supremum_rec(page)
		       && page_rec_get_next(rec)
					!= page_get_supremum_rec(page)) {
		while (rec != supremum) {
			rec_t*	next_rec = page_rec_get_next(rec);
			if (next_rec == supremum) {
				break;
			}

			matched_fields = 0;
			matched_bytes = 0;
			offsets1 = rec_get_offsets(rec, index, offsets1,
						ULINT_UNDEFINED, &heap);
			offsets2 = rec_get_offsets(next_rec, index, offsets2,
			offsets_next_rec = rec_get_offsets(next_rec, index,
						offsets_next_rec,
						n_cols, &heap);

			cmp_rec_rec_with_match(rec, next_rec,
						offsets1, offsets2,
						offsets_rec, offsets_next_rec,
						index, &matched_fields,
						&matched_bytes);

@@ -2874,9 +2887,17 @@ btr_estimate_number_of_different_key_vals(

			total_external_size +=
				btr_rec_get_externally_stored_len(
								rec, offsets1);
								rec, offsets_rec);
			
			rec = page_rec_get_next(rec);
			rec = next_rec;
			/* Initialize offsets_rec for the next round
			and assign the old offsets_rec buffer to
			offsets_next_rec. */
			{
				ulint*	offsets_tmp = offsets_rec;
				offsets_rec = offsets_next_rec;
				offsets_next_rec = offsets_tmp;
			}
		}
		

@@ -2898,11 +2919,11 @@ btr_estimate_number_of_different_key_vals(
			}
		}

		offsets1 = rec_get_offsets(rec, index, offsets1,
		offsets_rec = rec_get_offsets(rec, index, offsets_rec,
						ULINT_UNDEFINED, &heap);
		total_external_size +=
				btr_rec_get_externally_stored_len(rec,
								offsets1);
								offsets_rec);
		mtr_commit(&mtr);
	}

@@ -3598,7 +3619,7 @@ btr_rec_free_externally_stored_fields(
							MTR_MEMO_PAGE_X_FIX));
	/* Free possible externally stored fields in the record */

	ut_ad(index->table->comp == rec_offs_comp(offsets));
	ut_ad(index->table->comp == !!rec_offs_comp(offsets));
	n_fields = rec_offs_n_fields(offsets);

	for (i = 0; i < n_fields; i++) {
+30 −36

File changed.

Preview size limit exceeded, changes collapsed.

+54 −85

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -736,7 +736,7 @@ dict_truncate_index_tree(
	dulint		index_id;
	byte*		ptr;
	ulint		len;
	ibool		comp;
	ulint		comp;
	dict_index_t*	index;

#ifdef UNIV_SYNC_DEBUG
Loading