52 static mutex_t btr_search_enabled_mutex;
55 UNIV_INTERN ulint btr_search_this_is_zero = 0;
57 #ifdef UNIV_SEARCH_PERF_STAT
59 UNIV_INTERN ulint btr_search_n_succ = 0;
61 UNIV_INTERN ulint btr_search_n_hash_fail = 0;
67 UNIV_INTERN byte btr_sea_pad1[64];
81 UNIV_INTERN byte btr_sea_pad2[64];
86 #ifdef UNIV_PFS_RWLOCK
88 UNIV_INTERN mysql_pfs_key_t btr_search_latch_key;
94 #define BTR_SEARCH_PAGE_BUILD_LIMIT 16
98 #define BTR_SEARCH_BUILD_LIMIT 100
107 btr_search_build_page_hash_index(
129 btr_search_check_free_space_in_heap(
void)
135 #ifdef UNIV_SYNC_DEBUG
148 if (heap->free_block == NULL) {
153 if (heap->free_block == NULL) {
154 heap->free_block = block;
178 mutex_create(btr_search_enabled_mutex_key,
179 &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
209 mutex_enter(&btr_search_enabled_mutex);
229 mutex_exit(&btr_search_enabled_mutex);
239 mutex_enter(&btr_search_enabled_mutex);
246 mutex_exit(&btr_search_enabled_mutex);
263 info->magic_n = BTR_SEARCH_MAGIC_N;
274 #ifdef UNIV_SEARCH_PERF_STAT
275 info->n_hash_succ = 0;
276 info->n_hash_fail = 0;
277 info->n_patt_succ = 0;
278 info->n_searches = 0;
304 #ifdef UNIV_SYNC_DEBUG
322 btr_search_info_update_hash(
331 #ifdef UNIV_SYNC_DEBUG
336 index = cursor->
index;
365 if (info->
left_side ? cmp <= 0 : cmp > 0) {
373 if (info->
left_side ? cmp <= 0 : cmp > 0) {
375 goto increment_potential;
397 }
else if (cmp > 0) {
443 btr_search_update_block_hash_info(
450 #ifdef UNIV_SYNC_DEBUG
453 ut_ad(rw_lock_own(&block->
lock, RW_LOCK_SHARED)
454 || rw_lock_own(&block->
lock, RW_LOCK_EX));
461 ut_ad(info->magic_n == BTR_SEARCH_MAGIC_N);
489 if (cursor->
index->
table->does_not_fit_in_memory) {
495 / BTR_SEARCH_PAGE_BUILD_LIMIT)
524 btr_search_update_hash_ref(
535 #ifdef UNIV_SYNC_DEBUG
537 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_SHARED)
538 || rw_lock_own(&(block->
lock), RW_LOCK_EX));
541 == buf_block_get_frame(block));
556 ulint offsets_[REC_OFFS_NORMAL_SIZE];
557 rec_offs_init(offsets_);
568 rec_get_offsets(rec, cursor->
index, offsets_,
569 ULINT_UNDEFINED, &heap),
572 if (UNIV_LIKELY_NULL(heap)) {
575 #ifdef UNIV_SYNC_DEBUG
588 btr_search_info_update_slow(
598 #ifdef UNIV_SYNC_DEBUG
610 btr_search_info_update_hash(info, cursor);
612 build_index = btr_search_update_block_hash_info(info, block, cursor);
616 btr_search_check_free_space_in_heap();
622 #ifdef UNIV_SEARCH_PERF_STAT
623 btr_search_n_hash_fail++;
628 btr_search_update_hash_ref(info, block, cursor);
642 params = (ulint *)mem_alloc(3 *
sizeof(ulint));
650 params2 = params + btr_search_this_is_zero;
652 btr_search_build_page_hash_index(cursor->
index,
668 btr_search_check_guess(
671 ibool can_only_compare_to_cursor_rec,
690 ulint offsets_[REC_OFFS_NORMAL_SIZE];
691 ulint* offsets = offsets_;
692 ibool success = FALSE;
693 rec_offs_init(offsets_);
704 offsets = rec_get_offsets(rec, cursor->
index, offsets,
707 offsets, &match, &bytes);
709 if (mode == PAGE_CUR_GE) {
716 if (match >= n_unique) {
720 }
else if (mode == PAGE_CUR_LE) {
727 }
else if (mode == PAGE_CUR_G) {
731 }
else if (mode == PAGE_CUR_L) {
737 if (can_only_compare_to_cursor_rec) {
746 if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) {
760 offsets = rec_get_offsets(prev_rec, cursor->
index, offsets,
763 offsets, &match, &bytes);
764 if (mode == PAGE_CUR_GE) {
789 offsets = rec_get_offsets(next_rec, cursor->
index, offsets,
792 offsets, &match, &bytes);
793 if (mode == PAGE_CUR_LE) {
801 if (UNIV_LIKELY_NULL(heap)) {
828 ulint has_search_latch,
842 ut_ad(index && info && tuple && cursor && mtr);
863 index_id = index->
id;
865 #ifdef UNIV_SEARCH_PERF_STAT
873 if (UNIV_LIKELY(!has_search_latch)) {
886 if (UNIV_UNLIKELY(!rec)) {
892 if (UNIV_LIKELY(!has_search_latch)) {
904 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
910 if (UNIV_LIKELY(!has_search_latch)) {
930 || !btr_search_check_guess(cursor,
933 if (UNIV_LIKELY(!has_search_latch)) {
952 ut_ad(!has_search_latch);
958 if (mode == PAGE_CUR_GE
967 btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode,
980 #ifdef UNIV_SEARCH_PERF_STAT
983 if (UNIV_LIKELY(!has_search_latch)
998 if (UNIV_LIKELY(!has_search_latch)) {
1004 #ifdef UNIV_SEARCH_PERF_STAT
1005 info->n_hash_fail++;
1007 if (info->n_hash_succ > 0) {
1008 info->n_hash_succ--;
1034 index_id_t index_id;
1043 #ifdef UNIV_SYNC_DEBUG
1050 page = block->
frame;
1061 #ifdef UNIV_SYNC_DEBUG
1062 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_SHARED)
1063 || rw_lock_own(&(block->
lock), RW_LOCK_EX)
1069 index = block->
index;
1078 ut_a(n_fields + n_bytes > 0);
1085 folds = (ulint *)mem_alloc(n_recs *
sizeof(ulint));
1089 rec = page_get_infimum_rec(page);
1094 ut_a(index_id == index->
id);
1102 offsets = rec_get_offsets(rec, index, offsets,
1103 n_fields + (n_bytes > 0), &heap);
1105 fold =
rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1107 if (fold == prev_fold && prev_fold != 0) {
1115 folds[n_cached] = fold;
1122 if (UNIV_LIKELY_NULL(heap)) {
1148 for (i = 0; i < n_cached; i++) {
1157 block->
index = NULL;
1160 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1161 if (UNIV_UNLIKELY(block->n_pointers)) {
1165 " InnoDB: Corruption of adaptive hash index."
1167 "InnoDB: the hash index to a page of %s,"
1168 " still %lu hash nodes remain.\n",
1169 index->
name, (ulong) block->n_pointers);
1172 btr_search_validate();
1219 if (UNIV_LIKELY(block != NULL)) {
1221 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
1236 btr_search_build_page_hash_index(
1251 index_id_t index_id;
1258 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1259 ulint* offsets = offsets_;
1260 rec_offs_init(offsets_);
1266 page = buf_block_get_frame(block);
1268 #ifdef UNIV_SYNC_DEBUG
1270 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_SHARED)
1271 || rw_lock_own(&(block->
lock), RW_LOCK_EX));
1296 if (n_fields + n_bytes == 0) {
1310 folds = (ulint *)mem_alloc(n_recs *
sizeof(ulint));
1311 recs = (rec_t **)mem_alloc(n_recs *
sizeof(rec_t*));
1319 offsets = rec_get_offsets(rec, index, offsets,
1320 n_fields + (n_bytes > 0), &heap);
1330 fold =
rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1334 folds[n_cached] = fold;
1335 recs[n_cached] = rec;
1346 folds[n_cached] = fold;
1347 recs[n_cached] = rec;
1354 offsets = rec_get_offsets(next_rec, index, offsets,
1355 n_fields + (n_bytes > 0), &heap);
1356 next_fold =
rec_fold(next_rec, offsets, n_fields,
1359 if (fold != next_fold) {
1364 folds[n_cached] = next_fold;
1365 recs[n_cached] = next_rec;
1368 folds[n_cached] = fold;
1369 recs[n_cached] = rec;
1378 btr_search_check_free_space_in_heap();
1407 block->
index = index;
1409 for (i = 0; i < n_cached; i++) {
1419 if (UNIV_LIKELY_NULL(heap)) {
1445 #ifdef UNIV_SYNC_DEBUG
1446 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1447 ut_ad(rw_lock_own(&(new_block->
lock), RW_LOCK_EX));
1477 ut_a(n_fields + n_bytes > 0);
1479 btr_search_build_page_hash_index(index, new_block, n_fields,
1480 n_bytes, left_side);
1504 index_id_t index_id;
1505 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1507 rec_offs_init(offsets_);
1513 #ifdef UNIV_SYNC_DEBUG
1514 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1529 fold =
rec_fold(rec, rec_get_offsets(rec, cursor->
index, offsets_,
1530 ULINT_UNDEFINED, &heap),
1532 if (UNIV_LIKELY_NULL(heap)) {
1561 #ifdef UNIV_SYNC_DEBUG
1562 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1609 index_id_t index_id;
1612 ulint next_fold = 0;
1616 ibool locked = FALSE;
1618 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1619 ulint* offsets = offsets_;
1620 rec_offs_init(offsets_);
1624 btr_search_check_free_space_in_heap();
1630 #ifdef UNIV_SYNC_DEBUG
1631 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1651 offsets = rec_get_offsets(ins_rec, cursor->
index, offsets,
1652 ULINT_UNDEFINED, &heap);
1653 ins_fold =
rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
1656 offsets = rec_get_offsets(next_rec, cursor->
index, offsets,
1657 n_fields + (n_bytes > 0), &heap);
1658 next_fold =
rec_fold(next_rec, offsets, n_fields,
1663 offsets = rec_get_offsets(rec, cursor->
index, offsets,
1664 n_fields + (n_bytes > 0), &heap);
1665 fold =
rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1676 goto check_next_rec;
1679 if (fold != ins_fold) {
1712 if (ins_fold != next_fold) {
1735 if (UNIV_LIKELY_NULL(heap)) {
1743 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1749 btr_search_validate(
void)
1753 ulint n_page_dumps = 0;
1758 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1759 ulint* offsets = offsets_;
1763 ulint chunk_size = 10000;
1765 rec_offs_init(offsets_);
1772 for (i = 0; i < cell_count; i++) {
1775 if ((i != 0) && ((i % chunk_size) == 0)) {
1785 for (; node != NULL; node = node->
next) {
1790 index_id_t page_index_id;
1811 ut_a(hash_block == block);
1829 offsets = rec_get_offsets((
const rec_t*) node->
data,
1830 block->
index, offsets,
1850 " InnoDB: Error in an adaptive hash"
1851 " index pointer to page %lu\n"
1852 "InnoDB: ptr mem address %p"
1854 " node fold %lu, rec fold %lu\n",
1857 (ullint) page_index_id,
1865 fputs(
"InnoDB: Record ", stderr);
1868 fprintf(stderr,
"\nInnoDB: on that page."
1869 " Page mem address %p, is hashed %lu,"
1870 " n fields %lu, n bytes %lu\n"
1871 "InnoDB: side %lu\n",
1877 if (n_page_dumps < 20) {
1885 for (i = 0; i < cell_count; i += chunk_size) {
1886 ulint end_index =
ut_min(i + chunk_size - 1, cell_count - 1);
1905 if (UNIV_LIKELY_NULL(heap)) {
UNIV_INTERN void btr_search_drop_page_hash_when_freed(ulint space, ulint zip_size, ulint page_no)
UNIV_INLINE ulint page_is_comp(const page_t *page)
#define rw_lock_create(K, L, level)
UNIV_INTERN void btr_search_move_or_delete_hash_entries(buf_block_t *new_block, buf_block_t *block, dict_index_t *index)
UNIV_INLINE void btr_leaf_page_release(buf_block_t *block, ulint latch_mode, mtr_t *mtr)
UNIV_INTERN void btr_search_update_hash_on_delete(btr_cur_t *cursor)
UNIV_INTERN ibool btr_search_guess_on_hash(dict_index_t *index, btr_search_t *info, const dtuple_t *tuple, ulint mode, ulint latch_mode, btr_cur_t *cursor, ulint has_search_latch, mtr_t *mtr)
UNIV_INLINE page_t * page_align(const void *ptr) __attribute__((const ))
UNIV_INLINE ulint page_get_page_no(const page_t *page)
#define buf_block_state_valid(block)
UNIV_INTERN void btr_cur_search_to_nth_level(dict_index_t *index, ulint level, const dtuple_t *tuple, ulint mode, ulint latch_mode, btr_cur_t *cursor, ulint has_search_latch, const char *file, ulint line, mtr_t *mtr)
UNIV_INLINE ulint page_get_n_recs(const page_t *page)
btr_search_sys_t * btr_search_sys
UNIV_INTERN void buf_page_print(const byte *read_buf, ulint zip_size)
UNIV_INLINE const rec_t * page_rec_get_next_low(const rec_t *rec, ulint comp)
UNIV_INTERN void rec_print_new(FILE *file, const rec_t *rec, const ulint *offsets)
#define ha_create(n_c, n_m, level)
UNIV_INLINE int page_cmp_dtuple_rec_with_match(const dtuple_t *dtuple, const rec_t *rec, const ulint *offsets, ulint *matched_fields, ulint *matched_bytes)
UNIV_INLINE rec_t * page_rec_get_next(rec_t *rec)
UNIV_INLINE void buf_pool_mutex_enter_all(void)
UNIV_INTERN void btr_search_sys_create(ulint hash_size)
#define mem_heap_free(heap)
UNIV_INLINE ulint btr_page_get_prev(const page_t *page, mtr_t *mtr)
UNIV_INTERN void ha_remove_all_nodes_to_page(hash_table_t *table, ulint fold, const page_t *page)
UNIV_INLINE ulint rw_lock_get_writer(const rw_lock_t *lock)
UNIV_INLINE void buf_pool_mutex_exit_all(void)
UNIV_INTERN void btr_search_disable(void)
ibool btr_search_fully_disabled
UNIV_INLINE ulint dtuple_get_n_fields(const dtuple_t *tuple)
UNIV_INLINE ulint btr_page_get_next(const page_t *page, mtr_t *mtr)
UNIV_INLINE rec_t * page_rec_get_prev(rec_t *rec)
The buffer pool structure.
UNIV_INLINE ulint ut_min(ulint n1, ulint n2)
UNIV_INTERN void hash_table_free(hash_table_t *table)
UNIV_INLINE ulint dict_index_get_n_unique_in_tree(const dict_index_t *index)
UNIV_INTERN btr_search_t * btr_search_info_create(mem_heap_t *heap)
UNIV_INTERN void os_thread_yield(void)
UNIV_INLINE ulint buf_block_get_page_no(const buf_block_t *block) __attribute__((pure))
UNIV_INLINE void * ha_search_and_get_data(hash_table_t *table, ulint fold)
UNIV_INTERN void mtr_commit(mtr_t *mtr) __attribute__((nonnull))
UNIV_INLINE ibool buf_page_peek_if_too_old(const buf_page_t *bpage)
UNIV_INLINE index_id_t btr_page_get_index_id(const page_t *page)
UNIV_INLINE ulint page_rec_is_comp(const rec_t *rec)
UNIV_INLINE enum buf_page_state buf_block_get_state(const buf_block_t *block) __attribute__((pure))
UNIV_INTERN ibool buf_page_peek_if_search_hashed(ulint space, ulint offset)
rw_lock_t * btr_search_latch_temp
The latch protecting the adaptive search system.
UNIV_INTERN ibool buf_page_get_known_nowait(ulint rw_latch, buf_block_t *block, ulint mode, const char *file, ulint line, mtr_t *mtr)
UNIV_INTERN void btr_search_sys_free(void)
UNIV_INLINE ulint rec_fold(const rec_t *rec, const ulint *offsets, ulint n_fields, ulint n_bytes, index_id_t tree_id) __attribute__((pure))
UNIV_INTERN buf_block_t * buf_block_alloc(buf_pool_t *buf_pool)
UNIV_INLINE rec_t * btr_cur_get_rec(btr_cur_t *cursor)
UNIV_INTERN void btr_search_update_hash_on_insert(btr_cur_t *cursor)
btr_search_t * search_info
UNIV_INLINE void * mem_heap_alloc(mem_heap_t *heap, ulint n)
UNIV_INLINE ibool page_rec_is_supremum(const rec_t *rec) __attribute__((const ))
#define ha_insert_for_fold(t, f, b, d)
UNIV_INTERN buf_block_t * buf_page_get_gen(ulint space, ulint zip_size, ulint offset, ulint rw_latch, buf_block_t *guess, ulint mode, const char *file, ulint line, mtr_t *mtr)
UNIV_INLINE ulint rec_offs_n_fields(const ulint *offsets)
UNIV_INLINE ibool ha_search_and_delete_if_found(hash_table_t *table, ulint fold, void *data)
hash_table_t * hash_index
UNIV_INLINE ulint rw_lock_get_reader_count(const rw_lock_t *lock)
#define rw_lock_s_lock(M)
UNIV_INTERN void btr_search_drop_page_hash_index(buf_block_t *block)
UNIV_INLINE buf_pool_t * buf_pool_from_bpage(const buf_page_t *bpage)
UNIV_INLINE buf_block_t * buf_block_hash_get(buf_pool_t *buf_pool, ulint space, ulint offset)
UNIV_INLINE hash_cell_t * hash_get_nth_cell(hash_table_t *table, ulint n)
UNIV_INLINE ulint buf_block_get_space(const buf_block_t *block) __attribute__((pure))
UNIV_INTERN void btr_search_update_hash_node_on_insert(btr_cur_t *cursor)
UNIV_INLINE ibool page_rec_is_user_rec(const rec_t *rec) __attribute__((const ))
UNIV_INLINE void btr_cur_position(dict_index_t *index, rec_t *rec, buf_block_t *block, btr_cur_t *cursor)
UNIV_INTERN void ut_print_timestamp(FILE *file)
UNIV_INLINE ulint dtuple_fold(const dtuple_t *tuple, ulint n_fields, ulint n_bytes, index_id_t tree_id) __attribute__((pure))
UNIV_INLINE buf_block_t * btr_cur_get_block(btr_cur_t *cursor)
#define ha_search_and_update_if_found(table, fold, data, new_block, new_data)
UNIV_INTERN buf_block_t * buf_block_align(const byte *ptr)
UNIV_INLINE void mtr_start(mtr_t *mtr) __attribute__((nonnull))
UNIV_INTERN void buf_pool_drop_hash_index(void)
UNIV_INTERN void buf_page_make_young(buf_page_t *bpage)
UNIV_INLINE ibool page_rec_is_infimum(const rec_t *rec) __attribute__((const ))
UNIV_INLINE int ut_pair_cmp(ulint a1, ulint a2, ulint b1, ulint b2)
UNIV_INLINE void buf_block_free(buf_block_t *block)
UNIV_INTERN ulint btr_search_info_get_ref_count(btr_search_t *info)
UNIV_INLINE ulint dict_index_is_ibuf(const dict_index_t *index) __attribute__((pure))
UNIV_INTERN void btr_search_enable(void)
#define BUF_PEEK_IF_IN_POOL
UNIV_INLINE ulint hash_get_n_cells(hash_table_t *table)