diff options
author | Monty <monty@mariadb.org> | 2020-02-27 19:12:27 +0200 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2020-03-27 03:54:45 +0200 |
commit | f36ca142f7fa59598e34e842b60372b963067766 (patch) | |
tree | 4b797dcf88e98fd9fe83e3a29bfaabc10b7219c2 /storage/innobase | |
parent | 9b061990801b5c8309149794145f9c361bb8cfc6 (diff) | |
download | mariadb-git-f36ca142f7fa59598e34e842b60372b963067766.tar.gz |
Added page_range to records_in_range() to improve range statistics
Prototype change:
- virtual ha_rows records_in_range(uint inx, key_range *min_key,
- key_range *max_key)
+ virtual ha_rows records_in_range(uint inx, const key_range *min_key,
+ const key_range *max_key,
+ page_range *res)
The handler can ignore the page_range parameter. In the case the handler
updates the parameter, the optimizer can deduce the following:
- If previous range's last key is on the same block as next range's first
key
- If the current key range is in one block
- We can also assume that the first and last block read are cached!
This can be used for a better calculation of IO seeks when we
estimate the cost of a range index scan.
The parameter is fully implemented for MyISAM, Aria and InnoDB.
A separate patch will update handler::multi_range_read_info_const() to
take the benefits of this change and also remove the double
records_in_range() calls that are not anymore needed.
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/btr/btr0cur.cc | 41 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 11 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 7 | ||||
-rw-r--r-- | storage/innobase/include/btr0cur.h | 37 | ||||
-rw-r--r-- | storage/innobase/include/buf0types.h | 2 |
5 files changed, 64 insertions, 34 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index ba5979ff1c6..8a547669894 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -6135,10 +6135,8 @@ static const ha_rows rows_in_range_arbitrary_ret_val = 10; /** Estimates the number of rows in a given index range. @param[in] index index -@param[in] tuple1 range start, may also be empty tuple -@param[in] mode1 search mode for range start -@param[in] tuple2 range end, may also be empty tuple -@param[in] mode2 search mode for range end +@param[in] tuple1 range start +@param[in] tuple2 range end @param[in] nth_attempt if the tree gets modified too much while we are trying to analyze it, then we will retry (this function will call itself, incrementing this parameter) @@ -6151,10 +6149,8 @@ static ha_rows btr_estimate_n_rows_in_range_low( dict_index_t* index, - const dtuple_t* tuple1, - page_cur_mode_t mode1, - const dtuple_t* tuple2, - page_cur_mode_t mode2, + btr_pos_t* tuple1, + btr_pos_t* tuple2, unsigned nth_attempt) { btr_path_t path1[BTR_PATH_ARRAY_N_SLOTS]; @@ -6170,6 +6166,7 @@ btr_estimate_n_rows_in_range_low( ulint i; mtr_t mtr; ha_rows table_n_rows; + page_cur_mode_t mode2= tuple2->mode; table_n_rows = dict_table_get_n_rows(index->table); @@ -6188,9 +6185,10 @@ btr_estimate_n_rows_in_range_low( bool should_count_the_left_border; - if (dtuple_get_n_fields(tuple1) > 0) { + if (dtuple_get_n_fields(tuple1->tuple) > 0) { - btr_cur_search_to_nth_level(index, 0, tuple1, mode1, + btr_cur_search_to_nth_level(index, 0, tuple1->tuple, + tuple1->mode, BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, 0, __FILE__, __LINE__, &mtr); @@ -6230,6 +6228,8 @@ btr_estimate_n_rows_in_range_low( should_count_the_left_border = false; } + tuple1->page_id= cursor.page_cur.block->page.id; + mtr_commit(&mtr); if (!index->is_readable()) { @@ -6242,9 +6242,10 @@ btr_estimate_n_rows_in_range_low( bool should_count_the_right_border; - if (dtuple_get_n_fields(tuple2) > 0) { + if (dtuple_get_n_fields(tuple2->tuple) > 0) { - btr_cur_search_to_nth_level(index, 0, tuple2, mode2, + btr_cur_search_to_nth_level(index, 0, tuple2->tuple, + mode2, BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, 0, __FILE__, __LINE__, &mtr); @@ -6256,7 +6257,7 @@ btr_estimate_n_rows_in_range_low( should_count_the_right_border = (mode2 == PAGE_CUR_LE /* if the range is '<=' */ /* and the record was found */ - && cursor.low_match >= dtuple_get_n_fields(tuple2)) + && cursor.low_match >= dtuple_get_n_fields(tuple2->tuple)) || (mode2 == PAGE_CUR_L /* or if the range is '<' */ /* and there are any records to match the criteria, i.e. if the minimum record on the tree is 5 and @@ -6300,6 +6301,8 @@ btr_estimate_n_rows_in_range_low( should_count_the_right_border = false; } + tuple2->page_id= cursor.page_cur.block->page.id; + mtr_commit(&mtr); /* We have the path information for the range in path1 and path2 */ @@ -6438,8 +6441,8 @@ btr_estimate_n_rows_in_range_low( } return btr_estimate_n_rows_in_range_low( - index, tuple1, mode1, - tuple2, mode2, nth_attempt + 1); + index, tuple1, tuple2, + nth_attempt + 1); } diverged = true; @@ -6510,13 +6513,11 @@ btr_estimate_n_rows_in_range_low( ha_rows btr_estimate_n_rows_in_range( dict_index_t* index, - const dtuple_t* tuple1, - page_cur_mode_t mode1, - const dtuple_t* tuple2, - page_cur_mode_t mode2) + btr_pos_t *tuple1, + btr_pos_t *tuple2) { return btr_estimate_n_rows_in_range_low( - index, tuple1, mode1, tuple2, mode2, 1); + index, tuple1, tuple2, 1); } /*******************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 2d3471fd65c..9c5db57c661 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13936,10 +13936,11 @@ ha_rows ha_innobase::records_in_range( /*==========================*/ uint keynr, /*!< in: index number */ - key_range *min_key, /*!< in: start key value of the + const key_range *min_key, /*!< in: start key value of the range, may also be 0 */ - key_range *max_key) /*!< in: range end key val, may + const key_range *max_key, /*!< in: range end key val, may also be 0 */ + page_range *pages) { KEY* key; dict_index_t* index; @@ -14028,8 +14029,12 @@ ha_innobase::records_in_range( n_rows = rtr_estimate_n_rows_in_range( index, range_start, mode1); } else { + btr_pos_t tuple1(range_start, mode1, pages->first_page); + btr_pos_t tuple2(range_end, mode2, pages->last_page); n_rows = btr_estimate_n_rows_in_range( - index, range_start, mode1, range_end, mode2); + index, &tuple1, &tuple2); + pages->first_page= tuple1.page_id.raw(); + pages->last_page= tuple2.page_id.raw(); } } else { diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 980c5b06ea5..d48c14da970 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -184,9 +184,10 @@ public: int start_stmt(THD *thd, thr_lock_type lock_type) override; ha_rows records_in_range( - uint inx, - key_range* min_key, - key_range* max_key) override; + uint inx, + const key_range* min_key, + const key_range* max_key, + page_range* pages) override; ha_rows estimate_rows_upper_bound() override; diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 0a45c3bb45f..9d5c9283e3b 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -555,20 +555,41 @@ btr_cur_pessimistic_delete( @param[in,out] mtr mini-transaction */ void btr_cur_node_ptr_delete(btr_cur_t* parent, mtr_t* mtr) MY_ATTRIBUTE((nonnull)); +/***********************************************************//** +Parses a redo log record of updating a record in-place. +@return end of log record or NULL */ +byte* +btr_cur_parse_update_in_place( +/*==========================*/ + byte* ptr, /*!< in: buffer */ + byte* end_ptr,/*!< in: buffer end */ + page_t* page, /*!< in/out: page or NULL */ + page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ + dict_index_t* index); /*!< in: index corresponding to page */ +/** Arguments to btr_estimate_n_rows_in_range */ +struct btr_pos_t +{ + btr_pos_t(dtuple_t *arg_tuple, + page_cur_mode_t arg_mode, + page_id_t arg_page_id) + :tuple(arg_tuple), mode(arg_mode), page_id(arg_page_id) + {} + + dtuple_t* tuple; /* Range start or end. May be NULL */ + page_cur_mode_t mode; /* search mode for range */ + page_id_t page_id; /* Out: Page where we found the tuple */ +}; + /** Estimates the number of rows in a given index range. @param[in] index index -@param[in] tuple1 range start, may also be empty tuple -@param[in] mode1 search mode for range start -@param[in] tuple2 range end, may also be empty tuple -@param[in] mode2 search mode for range end +@param[in/out] range_start +@param[in/out] range_ end @return estimated number of rows */ ha_rows btr_estimate_n_rows_in_range( dict_index_t* index, - const dtuple_t* tuple1, - page_cur_mode_t mode1, - const dtuple_t* tuple2, - page_cur_mode_t mode2); + btr_pos_t* range_start, + btr_pos_t* range_end); /*******************************************************************//** Estimates the number of different key values in a given index, for diff --git a/storage/innobase/include/buf0types.h b/storage/innobase/include/buf0types.h index 124a7f1854f..34146ccdfa5 100644 --- a/storage/innobase/include/buf0types.h +++ b/storage/innobase/include/buf0types.h @@ -141,6 +141,7 @@ public: ut_ad(page_no <= 0xFFFFFFFFU); } + page_id_t(ulonglong id) : m_id(id) {} bool operator==(const page_id_t& rhs) const { return m_id == rhs.m_id; } bool operator!=(const page_id_t& rhs) const { return m_id != rhs.m_id; } @@ -169,6 +170,7 @@ public: /** Set the FIL_NULL for the space and page_no */ void set_corrupt_id() { m_id= ~uint64_t{0}; } + ulonglong raw() { return m_id; } private: /** The page identifier */ uint64_t m_id; |