mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
InnoDB: optimize SELECT performance
innobase/include/row0vers.h: row_vers_build_for_consistent_read(): Add parameters offsets and offset_heap in order to avoid recomputing the offsets in the caller. innobase/row/row0sel.c: Eliminate some rec_get_offsets() calls. innobase/row/row0vers.c: row_vers_build_for_consistent_read(): Add parameters offsets and offset_heap in order to avoid recomputing the offsets in the caller.
This commit is contained in:
parent
77174b3a89
commit
2a66f66dfb
3 changed files with 67 additions and 45 deletions
|
@ -79,7 +79,11 @@ row_vers_build_for_consistent_read(
|
|||
mtr_t* mtr, /* in: mtr holding the latch on rec; it will
|
||||
also hold the latch on purge_view */
|
||||
dict_index_t* index, /* in: the clustered index */
|
||||
ulint** offsets,/* in/out: offsets returned by
|
||||
rec_get_offsets(rec, index) */
|
||||
read_view_t* view, /* in: the consistent read view */
|
||||
mem_heap_t** offset_heap,/* in/out: memory heap from which
|
||||
the offsets are allocated */
|
||||
mem_heap_t* in_heap,/* in: memory heap from which the memory for
|
||||
old_vers is allocated; memory for possible
|
||||
intermediate versions is allocated and freed
|
||||
|
|
|
@ -510,6 +510,10 @@ row_sel_build_prev_vers(
|
|||
read_view_t* read_view, /* in: read view */
|
||||
plan_t* plan, /* in: plan node for table */
|
||||
rec_t* rec, /* in: record in a clustered index */
|
||||
ulint** offsets, /* in/out: offsets returned by
|
||||
rec_get_offsets(rec, plan->index) */
|
||||
mem_heap_t** offset_heap, /* in/out: memory heap from which
|
||||
the offsets are allocated */
|
||||
rec_t** old_vers, /* out: old version, or NULL if the
|
||||
record does not exist in the view:
|
||||
i.e., it was freshly inserted
|
||||
|
@ -525,8 +529,8 @@ row_sel_build_prev_vers(
|
|||
}
|
||||
|
||||
err = row_vers_build_for_consistent_read(rec, mtr, plan->index,
|
||||
read_view, plan->old_vers_heap,
|
||||
old_vers);
|
||||
offsets, read_view, offset_heap,
|
||||
plan->old_vers_heap, old_vers);
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
@ -697,7 +701,8 @@ row_sel_get_clust_rec(
|
|||
node->read_view)) {
|
||||
|
||||
err = row_sel_build_prev_vers(node->read_view, plan,
|
||||
clust_rec, &old_vers, mtr);
|
||||
clust_rec, &offsets, &heap,
|
||||
&old_vers, mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto err_exit;
|
||||
|
@ -1396,14 +1401,18 @@ rec_loop:
|
|||
node->read_view)) {
|
||||
|
||||
err = row_sel_build_prev_vers(node->read_view,
|
||||
plan, rec, &old_vers,
|
||||
&mtr);
|
||||
plan, rec,
|
||||
&offsets, &heap,
|
||||
&old_vers, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
if (old_vers == NULL) {
|
||||
offsets = rec_get_offsets(
|
||||
rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
row_sel_fetch_columns(index, rec,
|
||||
offsets,
|
||||
UT_LIST_GET_FIRST(plan->columns));
|
||||
|
@ -1417,8 +1426,6 @@ rec_loop:
|
|||
}
|
||||
|
||||
rec = old_vers;
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
}
|
||||
} else if (!lock_sec_rec_cons_read_sees(rec, index,
|
||||
node->read_view)) {
|
||||
|
@ -2535,6 +2542,10 @@ row_sel_build_prev_vers_for_mysql(
|
|||
dict_index_t* clust_index, /* in: clustered index */
|
||||
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
|
||||
rec_t* rec, /* in: record in a clustered index */
|
||||
ulint** offsets, /* in/out: offsets returned by
|
||||
rec_get_offsets(rec, clust_index) */
|
||||
mem_heap_t** offset_heap, /* in/out: memory heap from which
|
||||
the offsets are allocated */
|
||||
rec_t** old_vers, /* out: old version, or NULL if the
|
||||
record does not exist in the view:
|
||||
i.e., it was freshly inserted
|
||||
|
@ -2550,8 +2561,8 @@ row_sel_build_prev_vers_for_mysql(
|
|||
}
|
||||
|
||||
err = row_vers_build_for_consistent_read(rec, mtr, clust_index,
|
||||
read_view, prebuilt->old_vers_heap,
|
||||
old_vers);
|
||||
offsets, read_view, offset_heap,
|
||||
prebuilt->old_vers_heap, old_vers);
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
@ -2575,6 +2586,10 @@ row_sel_get_clust_rec_for_mysql(
|
|||
it, NULL if the old version did not exist
|
||||
in the read view, i.e., it was a fresh
|
||||
inserted version */
|
||||
ulint** offsets,/* out: offsets returned by
|
||||
rec_get_offsets(out_rec, clust_index) */
|
||||
mem_heap_t** offset_heap,/* in/out: memory heap from which
|
||||
the offsets are allocated */
|
||||
mtr_t* mtr) /* in: mtr used to get access to the
|
||||
non-clustered record; the same mtr is used to
|
||||
access the clustered index */
|
||||
|
@ -2584,9 +2599,6 @@ row_sel_get_clust_rec_for_mysql(
|
|||
rec_t* old_vers;
|
||||
ulint err;
|
||||
trx_t* trx;
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[100] = { 100, };
|
||||
ulint* offsets = offsets_;
|
||||
|
||||
*out_rec = NULL;
|
||||
trx = thr_get_trx(thr);
|
||||
|
@ -2642,8 +2654,8 @@ row_sel_get_clust_rec_for_mysql(
|
|||
goto func_exit;
|
||||
}
|
||||
|
||||
offsets = rec_get_offsets(clust_rec, clust_index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
*offsets = rec_get_offsets(clust_rec, clust_index, *offsets,
|
||||
ULINT_UNDEFINED, offset_heap);
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
/* Try to place a lock on the index record; we are searching
|
||||
|
@ -2651,7 +2663,7 @@ row_sel_get_clust_rec_for_mysql(
|
|||
we set a LOCK_REC_NOT_GAP type lock */
|
||||
|
||||
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
|
||||
clust_index, offsets,
|
||||
clust_index, *offsets,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_REC_NOT_GAP, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
@ -2669,11 +2681,12 @@ row_sel_get_clust_rec_for_mysql(
|
|||
|
||||
if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
|
||||
&& !lock_clust_rec_cons_read_sees(clust_rec, clust_index,
|
||||
offsets, trx->read_view)) {
|
||||
*offsets, trx->read_view)) {
|
||||
|
||||
err = row_sel_build_prev_vers_for_mysql(
|
||||
trx->read_view, clust_index,
|
||||
prebuilt, clust_rec,
|
||||
offsets, offset_heap,
|
||||
&old_vers, mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
@ -2722,9 +2735,6 @@ func_exit:
|
|||
|
||||
err = DB_SUCCESS;
|
||||
err_exit:
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
@ -3671,6 +3681,7 @@ rec_loop:
|
|||
err = row_sel_build_prev_vers_for_mysql(
|
||||
trx->read_view, clust_index,
|
||||
prebuilt, rec,
|
||||
&offsets, &heap,
|
||||
&old_vers, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
@ -3723,7 +3734,8 @@ rec_loop:
|
|||
mtr_has_extra_clust_latch = TRUE;
|
||||
|
||||
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
|
||||
thr, &clust_rec, &mtr);
|
||||
thr, &clust_rec,
|
||||
&offsets, &heap, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
|
@ -3745,20 +3757,18 @@ rec_loop:
|
|||
|
||||
if (prebuilt->need_to_access_clustered) {
|
||||
rec = clust_rec;
|
||||
ut_ad(rec_offs_validate(rec, clust_index, offsets));
|
||||
} else {
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
}
|
||||
}
|
||||
|
||||
if (prebuilt->need_to_access_clustered) {
|
||||
ut_ad(rec == clust_rec || index == clust_index);
|
||||
offsets = rec_get_offsets(rec, clust_index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
} else {
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
}
|
||||
|
||||
/* We found a qualifying row */
|
||||
|
||||
ut_ad(rec_offs_validate(rec,
|
||||
rec == clust_rec ? clust_index : index,
|
||||
offsets));
|
||||
|
||||
if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
|
||||
&& prebuilt->select_lock_type == LOCK_NONE
|
||||
&& !prebuilt->templ_contains_blob
|
||||
|
@ -3800,8 +3810,11 @@ rec_loop:
|
|||
}
|
||||
|
||||
if (prebuilt->clust_index_was_generated) {
|
||||
offsets = rec_get_offsets(index_rec, index, offsets,
|
||||
if (rec != index_rec) {
|
||||
offsets = rec_get_offsets(
|
||||
index_rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
}
|
||||
row_sel_store_row_id_to_prebuilt(prebuilt, index_rec,
|
||||
index, offsets);
|
||||
}
|
||||
|
|
|
@ -406,7 +406,11 @@ row_vers_build_for_consistent_read(
|
|||
of this records */
|
||||
mtr_t* mtr, /* in: mtr holding the latch on rec */
|
||||
dict_index_t* index, /* in: the clustered index */
|
||||
ulint** offsets,/* in/out: offsets returned by
|
||||
rec_get_offsets(rec, index) */
|
||||
read_view_t* view, /* in: the consistent read view */
|
||||
mem_heap_t** offset_heap,/* in/out: memory heap from which
|
||||
the offsets are allocated */
|
||||
mem_heap_t* in_heap,/* in: memory heap from which the memory for
|
||||
old_vers is allocated; memory for possible
|
||||
intermediate versions is allocated and freed
|
||||
|
@ -418,11 +422,9 @@ row_vers_build_for_consistent_read(
|
|||
rec_t* version;
|
||||
rec_t* prev_version;
|
||||
dulint prev_trx_id;
|
||||
mem_heap_t* heap;
|
||||
mem_heap_t* heap2;
|
||||
mem_heap_t* heap = NULL;
|
||||
byte* buf;
|
||||
ulint err;
|
||||
ulint* offsets;
|
||||
|
||||
ut_ad(index->type & DICT_CLUSTERED);
|
||||
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|
||||
|
@ -432,22 +434,23 @@ row_vers_build_for_consistent_read(
|
|||
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
heap = mem_heap_create(1024);
|
||||
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
|
||||
ut_ad(rec_offs_validate(rec, index, *offsets));
|
||||
|
||||
ut_ad(!read_view_sees_trx_id(view,
|
||||
row_get_rec_trx_id(rec, index, offsets)));
|
||||
row_get_rec_trx_id(rec, index, *offsets)));
|
||||
|
||||
rw_lock_s_lock(&(purge_sys->latch));
|
||||
version = rec;
|
||||
|
||||
for (;;) {
|
||||
heap2 = heap;
|
||||
mem_heap_t* heap2 = heap;
|
||||
heap = mem_heap_create(1024);
|
||||
|
||||
err = trx_undo_prev_version_build(rec, mtr, version, index,
|
||||
offsets, heap, &prev_version);
|
||||
mem_heap_free(heap2); /* free version and offsets */
|
||||
*offsets, heap, &prev_version);
|
||||
if (heap2) {
|
||||
mem_heap_free(heap2); /* free version */
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
break;
|
||||
|
@ -461,17 +464,19 @@ row_vers_build_for_consistent_read(
|
|||
break;
|
||||
}
|
||||
|
||||
offsets = rec_get_offsets(prev_version, index, NULL,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
prev_trx_id = row_get_rec_trx_id(prev_version, index, offsets);
|
||||
*offsets = rec_get_offsets(prev_version, index, *offsets,
|
||||
ULINT_UNDEFINED, offset_heap);
|
||||
prev_trx_id = row_get_rec_trx_id(prev_version, index,
|
||||
*offsets);
|
||||
|
||||
if (read_view_sees_trx_id(view, prev_trx_id)) {
|
||||
|
||||
/* The view already sees this version: we can copy
|
||||
it to in_heap and return */
|
||||
|
||||
buf = mem_heap_alloc(in_heap, rec_offs_size(offsets));
|
||||
*old_vers = rec_copy(buf, prev_version, offsets);
|
||||
buf = mem_heap_alloc(in_heap, rec_offs_size(*offsets));
|
||||
*old_vers = rec_copy(buf, prev_version, *offsets);
|
||||
rec_offs_make_valid(*old_vers, index, *offsets);
|
||||
err = DB_SUCCESS;
|
||||
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue