42
43
#include "btr0btr.h"
45
/* Flag: has the search system been enabled?
46
/** Flag: has the search system been enabled?
46
47
Protected by btr_search_latch and btr_search_enabled_mutex. */
47
48
UNIV_INTERN bool btr_search_enabled = TRUE;
50
/** Mutex protecting btr_search_enabled */
49
51
static mutex_t btr_search_enabled_mutex;
51
/* A dummy variable to fool the compiler */
53
/** A dummy variable to fool the compiler */
52
54
UNIV_INTERN ulint btr_search_this_is_zero = 0;
54
56
#ifdef UNIV_SEARCH_PERF_STAT
57
/** Number of successful adaptive hash index lookups */
55
58
UNIV_INTERN ulint btr_search_n_succ = 0;
59
/** Number of failed adaptive hash index lookups */
56
60
UNIV_INTERN ulint btr_search_n_hash_fail = 0;
57
61
#endif /* UNIV_SEARCH_PERF_STAT */
59
/* padding to prevent other memory update
63
/** padding to prevent other memory update
60
64
hotspots from residing on the same memory
61
65
cache line as btr_search_latch */
62
66
UNIV_INTERN byte btr_sea_pad1[64];
64
/* The latch protecting the adaptive search system: this latch protects the
68
/** The latch protecting the adaptive search system: this latch protects the
65
69
(1) positions of records on those pages where a hash index has been built.
66
70
NOTE: It does not protect values of non-ordering fields within a record from
67
71
being updated in-place! We can use fact (1) to perform unique searches to
71
75
same DRAM page as other hotspot semaphores */
72
76
UNIV_INTERN rw_lock_t* btr_search_latch_temp;
74
/* padding to prevent other memory update hotspots from residing on
78
/** padding to prevent other memory update hotspots from residing on
75
79
the same memory cache line */
76
80
UNIV_INTERN byte btr_sea_pad2[64];
82
/** The adaptive hash index */
78
83
UNIV_INTERN btr_search_sys_t* btr_search_sys;
80
/* If the number of records on the page divided by this parameter
85
/** If the number of records on the page divided by this parameter
81
86
would have been successfully accessed using a hash index, the index
82
87
is then built on the page, assuming the global limit has been reached */
84
88
#define BTR_SEARCH_PAGE_BUILD_LIMIT 16
86
/* The global limit for consecutive potentially successful hash searches,
90
/** The global limit for consecutive potentially successful hash searches,
87
91
before hash index building is started */
89
92
#define BTR_SEARCH_BUILD_LIMIT 100
91
/************************************************************************
94
/********************************************************************//**
92
95
Builds a hash index on a page with the given parameters. If the page already
93
96
has a hash index with different parameters, the old hash index is removed.
94
97
If index is non-NULL, this function checks if n_fields and n_bytes are
98
101
btr_search_build_page_hash_index(
99
102
/*=============================*/
100
dict_index_t* index, /* in: index for which to build, or NULL if
103
dict_index_t* index, /*!< in: index for which to build, or NULL if
102
buf_block_t* block, /* in: index page, s- or x-latched */
103
ulint n_fields,/* in: hash this many full fields */
104
ulint n_bytes,/* in: hash this many bytes from the next
105
buf_block_t* block, /*!< in: index page, s- or x-latched */
106
ulint n_fields,/*!< in: hash this many full fields */
107
ulint n_bytes,/*!< in: hash this many bytes from the next
106
ibool left_side);/* in: hash for searches from left side? */
109
ibool left_side);/*!< in: hash for searches from left side? */
108
/*********************************************************************
111
/*****************************************************************//**
109
112
This function should be called before reserving any btr search mutex, if
110
113
the intended operation might add nodes to the search system hash table.
111
114
Because of the latching order, once we have reserved the btr search system
154
/*********************************************************************
157
/*****************************************************************//**
155
158
Creates and initializes the adaptive search system at a database start. */
158
161
btr_search_sys_create(
159
162
/*==================*/
160
ulint hash_size) /* in: hash index hash table size */
163
ulint hash_size) /*!< in: hash index hash table size */
162
165
/* We allocate the search latch from dynamic memory:
163
166
see above at the global variable definition */
211
214
mutex_exit(&btr_search_enabled_mutex);
214
/*********************************************************************
215
Creates and initializes a search info struct. */
217
/*****************************************************************//**
218
Creates and initializes a search info struct.
219
@return own: search info struct */
218
222
btr_search_info_create(
219
223
/*===================*/
220
/* out, own: search info struct */
221
mem_heap_t* heap) /* in: heap where created */
224
mem_heap_t* heap) /*!< in: heap where created */
223
226
btr_search_t* info;
255
/*********************************************************************
258
/*****************************************************************//**
256
259
Returns the value of ref_count. The value is protected by
261
@return ref_count value. */
260
264
btr_search_info_get_ref_count(
261
265
/*==========================*/
262
/* out: ref_count value. */
263
btr_search_t* info) /* in: search info. */
266
btr_search_t* info) /*!< in: search info. */
287
290
btr_search_info_update_hash(
288
291
/*========================*/
289
btr_search_t* info, /* in/out: search info */
290
btr_cur_t* cursor) /* in: cursor which was just positioned */
292
btr_search_t* info, /*!< in/out: search info */
293
btr_cur_t* cursor) /*!< in: cursor which was just positioned */
292
295
dict_index_t* index;
401
/*************************************************************************
404
/*********************************************************************//**
402
405
Updates the block search info on hash successes. NOTE that info and
403
406
block->n_hash_helps, n_fields, n_bytes, side are NOT protected by any
404
semaphore, to save CPU time! Do not assume the fields are consistent. */
407
semaphore, to save CPU time! Do not assume the fields are consistent.
408
@return TRUE if building a (new) hash index on the block is recommended */
407
411
btr_search_update_block_hash_info(
408
412
/*==============================*/
409
/* out: TRUE if building a (new) hash index on
410
the block is recommended */
411
btr_search_t* info, /* in: search info */
412
buf_block_t* block, /* in: buffer block */
413
btr_search_t* info, /*!< in: search info */
414
buf_block_t* block, /*!< in: buffer block */
413
415
btr_cur_t* cursor __attribute__((unused)))
416
418
#ifdef UNIV_SYNC_DEBUG
417
419
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
480
/*************************************************************************
482
/*********************************************************************//**
481
483
Updates a hash node reference when it has been unsuccessfully used in a
482
484
search which could have succeeded with the used hash parameters. This can
483
485
happen because when building a hash index for a page, we do not check
490
492
btr_search_update_hash_ref(
491
493
/*=======================*/
492
btr_search_t* info, /* in: search info */
493
buf_block_t* block, /* in: buffer block where cursor positioned */
494
btr_cur_t* cursor) /* in: cursor */
494
btr_search_t* info, /*!< in: search info */
495
buf_block_t* block, /*!< in: buffer block where cursor positioned */
496
btr_cur_t* cursor) /*!< in: cursor */
550
/*************************************************************************
552
/*********************************************************************//**
551
553
Updates the search info. */
554
556
btr_search_info_update_slow(
555
557
/*========================*/
556
btr_search_t* info, /* in/out: search info */
557
btr_cur_t* cursor) /* in: cursor which was just positioned */
558
btr_search_t* info, /*!< in/out: search info */
559
btr_cur_t* cursor) /*!< in: cursor which was just positioned */
559
561
buf_block_t* block;
560
562
ibool build_index;
627
/**********************************************************************
629
/******************************************************************//**
628
630
Checks if a guessed position for a tree cursor is right. Note that if
629
631
mode is PAGE_CUR_LE, which is used in inserts, and the function returns
630
TRUE, then cursor->up_match and cursor->low_match both have sensible values. */
632
TRUE, then cursor->up_match and cursor->low_match both have sensible values.
633
@return TRUE if success */
633
636
btr_search_check_guess(
634
637
/*===================*/
635
/* out: TRUE if success */
636
btr_cur_t* cursor, /* in: guessed cursor position */
638
btr_cur_t* cursor, /*!< in: guessed cursor position */
637
639
ibool can_only_compare_to_cursor_rec,
638
/* in: if we do not have a latch on the page
640
/*!< in: if we do not have a latch on the page
639
641
of cursor, but only a latch on
640
642
btr_search_latch, then ONLY the columns
641
643
of the record UNDER the cursor are
642
644
protected, not the next or previous record
643
645
in the chain: we cannot look at the next or
644
646
previous record to check our guess! */
645
const dtuple_t* tuple, /* in: data tuple */
646
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
647
const dtuple_t* tuple, /*!< in: data tuple */
648
ulint mode, /*!< in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
647
649
or PAGE_CUR_GE */
648
mtr_t* mtr) /* in: mtr */
650
mtr_t* mtr) /*!< in: mtr */
773
/**********************************************************************
775
/******************************************************************//**
774
776
Tries to guess the right search position based on the hash search info
775
777
of the index. Note that if mode is PAGE_CUR_LE, which is used in inserts,
776
778
and the function returns TRUE, then cursor->up_match and cursor->low_match
777
both have sensible values. */
779
both have sensible values.
780
@return TRUE if succeeded */
780
783
btr_search_guess_on_hash(
781
784
/*=====================*/
782
/* out: TRUE if succeeded */
783
dict_index_t* index, /* in: index */
784
btr_search_t* info, /* in: index search info */
785
const dtuple_t* tuple, /* in: logical record */
786
ulint mode, /* in: PAGE_CUR_L, ... */
787
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...;
785
dict_index_t* index, /*!< in: index */
786
btr_search_t* info, /*!< in: index search info */
787
const dtuple_t* tuple, /*!< in: logical record */
788
ulint mode, /*!< in: PAGE_CUR_L, ... */
789
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ...;
788
790
NOTE that only if has_search_latch
789
791
is 0, we will have a latch set on
790
792
the cursor page, otherwise we assume
791
793
the caller uses his search latch
792
794
to protect the record! */
793
btr_cur_t* cursor, /* out: tree cursor */
794
ulint has_search_latch,/* in: latch mode the caller
795
btr_cur_t* cursor, /*!< out: tree cursor */
796
ulint has_search_latch,/*!< in: latch mode the caller
795
797
currently has on btr_search_latch:
796
798
RW_S_LATCH, RW_X_LATCH, or 0 */
797
mtr_t* mtr) /* in: mtr */
799
mtr_t* mtr) /*!< in: mtr */
799
801
buf_block_t* block;
982
/************************************************************************
984
/********************************************************************//**
983
985
Drops a page hash index. */
986
988
btr_search_drop_page_hash_index(
987
989
/*============================*/
988
buf_block_t* block) /* in: block containing index page,
990
buf_block_t* block) /*!< in: block containing index page,
989
991
s- or x-latched, or an index page
990
992
for which we know that
991
993
block->buf_fix_count == 0 */
1146
1148
mem_free(folds);
1149
/************************************************************************
1151
/********************************************************************//**
1150
1152
Drops a page hash index when a page is freed from a fseg to the file system.
1151
1153
Drops possible hash index if the page happens to be in the buffer pool. */
1154
1156
btr_search_drop_page_hash_when_freed(
1155
1157
/*=================================*/
1156
ulint space, /* in: space id */
1157
ulint zip_size, /* in: compressed page size in bytes
1158
ulint space, /*!< in: space id */
1159
ulint zip_size, /*!< in: compressed page size in bytes
1158
1160
or 0 for uncompressed pages */
1159
ulint page_no) /* in: page number */
1161
ulint page_no) /*!< in: page number */
1161
1163
buf_block_t* block;
1192
1194
mtr_commit(&mtr);
1195
/************************************************************************
1197
/********************************************************************//**
1196
1198
Builds a hash index on a page with the given parameters. If the page already
1197
1199
has a hash index with different parameters, the old hash index is removed.
1198
1200
If index is non-NULL, this function checks if n_fields and n_bytes are
1202
1204
btr_search_build_page_hash_index(
1203
1205
/*=============================*/
1204
dict_index_t* index, /* in: index for which to build */
1205
buf_block_t* block, /* in: index page, s- or x-latched */
1206
ulint n_fields,/* in: hash this many full fields */
1207
ulint n_bytes,/* in: hash this many bytes from the next
1206
dict_index_t* index, /*!< in: index for which to build */
1207
buf_block_t* block, /*!< in: index page, s- or x-latched */
1208
ulint n_fields,/*!< in: hash this many full fields */
1209
ulint n_bytes,/*!< in: hash this many bytes from the next
1209
ibool left_side)/* in: hash for searches from left side? */
1211
ibool left_side)/*!< in: hash for searches from left side? */
1211
1213
hash_table_t* table;
1390
/************************************************************************
1392
/********************************************************************//**
1391
1393
Moves or deletes hash entries for moved records. If new_page is already hashed,
1392
1394
then the hash index for page, if any, is dropped. If new_page is not hashed,
1393
1395
and page is hashed, then a new hash index is built to new_page with the same
1397
1399
btr_search_move_or_delete_hash_entries(
1398
1400
/*===================================*/
1399
buf_block_t* new_block, /* in: records are copied
1401
buf_block_t* new_block, /*!< in: records are copied
1400
1402
to this page */
1401
buf_block_t* block, /* in: index page from which
1403
buf_block_t* block, /*!< in: index page from which
1402
1404
records were copied, and the
1403
1405
copied records will be deleted
1404
1406
from this page */
1405
dict_index_t* index) /* in: record descriptor */
1407
dict_index_t* index) /*!< in: record descriptor */
1407
1409
ulint n_fields;
1453
1455
rw_lock_s_unlock(&btr_search_latch);
1456
/************************************************************************
1458
/********************************************************************//**
1457
1459
Updates the page hash index when a single record is deleted from a page. */
1460
1462
btr_search_update_hash_on_delete(
1461
1463
/*=============================*/
1462
btr_cur_t* cursor) /* in: cursor which was positioned on the
1464
btr_cur_t* cursor) /*!< in: cursor which was positioned on the
1463
1465
record to delete using btr_cur_search_...,
1464
1466
the record is not yet deleted */
1506
1508
rw_lock_x_unlock(&btr_search_latch);
1509
/************************************************************************
1511
/********************************************************************//**
1510
1512
Updates the page hash index when a single record is inserted on a page. */
1513
1515
btr_search_update_hash_node_on_insert(
1514
1516
/*==================================*/
1515
btr_cur_t* cursor) /* in: cursor which was positioned to the
1517
btr_cur_t* cursor) /*!< in: cursor which was positioned to the
1516
1518
place to insert using btr_cur_search_...,
1517
1519
and the new record has been inserted next
1518
1520
to the cursor */
1560
/************************************************************************
1562
/********************************************************************//**
1561
1563
Updates the page hash index when a single record is inserted on a page. */
1564
1566
btr_search_update_hash_on_insert(
1565
1567
/*=============================*/
1566
btr_cur_t* cursor) /* in: cursor which was positioned to the
1568
btr_cur_t* cursor) /*!< in: cursor which was positioned to the
1567
1569
place to insert using btr_cur_search_...,
1568
1570
and the new record has been inserted next
1569
1571
to the cursor */
1710
/************************************************************************
1711
Validates the search system. */
1712
/********************************************************************//**
1713
Validates the search system.
1714
@return TRUE if ok */
1714
1717
btr_search_validate(void)
1715
1718
/*=====================*/
1716
/* out: TRUE if ok */
1718
1720
ha_node_t* node;
1719
1721
ulint n_page_dumps = 0;