From ff878dc80df2f44fb442d6d8b96a68efe9a67f39 Mon Sep 17 00:00:00 2001 From: qichang Date: Thu, 14 Nov 2024 14:53:50 +0800 Subject: [PATCH] IO_COST --- mysql-test/suite/ctc/r/ctc_bit_analyze.result | 2 +- storage/ctc/ctc_srv.h | 3 ++ storage/ctc/ctc_srv_mq_stub.cc | 5 ++ storage/ctc/ha_ctc.cc | 42 ++++++++++++++++- storage/ctc/ha_ctc.h | 47 ++++++------------- storage/ctc/ha_ctcpart.cc | 35 ++++++++++++-- storage/ctc/ha_ctcpart.h | 2 + 7 files changed, 98 insertions(+), 38 deletions(-) diff --git a/mysql-test/suite/ctc/r/ctc_bit_analyze.result b/mysql-test/suite/ctc/r/ctc_bit_analyze.result index 7d18c30..fccc1c3 100644 --- a/mysql-test/suite/ctc/r/ctc_bit_analyze.result +++ b/mysql-test/suite/ctc/r/ctc_bit_analyze.result @@ -44,7 +44,7 @@ Warnings: Note 1003 /* select#1 */ select `test`.`tbl_bit`.`num` AS `num` from `test`.`tbl_bit` where ((`test`.`tbl_bit`.`num` > 0x02) and (`test`.`tbl_bit`.`num` < 0x0d)) explain select * from tbl_bit where num >= b'0010' and num <= b'1101'; id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE tbl_bit NULL index idx_num idx_num 2 NULL 16 75.00 Using where; Using index +1 SIMPLE tbl_bit NULL range idx_num idx_num 2 NULL 12 100.00 Using where; Using index Warnings: Note 1003 /* select#1 */ select `test`.`tbl_bit`.`num` AS `num` from `test`.`tbl_bit` where ((`test`.`tbl_bit`.`num` >= 0x02) and (`test`.`tbl_bit`.`num` <= 0x0d)) drop table tbl_bit; diff --git a/storage/ctc/ctc_srv.h b/storage/ctc/ctc_srv.h index 48045ac..1b01fc2 100644 --- a/storage/ctc/ctc_srv.h +++ b/storage/ctc/ctc_srv.h @@ -144,6 +144,8 @@ typedef struct { typedef struct { uint32_t estimate_rows; ctc_cbo_stats_column_t *columns; + uint32_t blocks; + uint32_t avg_row_len; } ctc_cbo_stats_table_t; /* @@ -160,6 +162,7 @@ typedef struct { uint32_t num_str_cols; bool *col_type; ctc_cbo_stats_table_t *ctc_cbo_stats_table; + uint32_t page_size; } ctc_cbo_stats_t; #pragma pack() diff --git a/storage/ctc/ctc_srv_mq_stub.cc b/storage/ctc/ctc_srv_mq_stub.cc index ad2f03b..c4518f4 100644 --- a/storage/ctc/ctc_srv_mq_stub.cc +++ b/storage/ctc/ctc_srv_mq_stub.cc @@ -771,16 +771,21 @@ void ctc_cbo_stats_copy_from_shm(ctc_handler_t *tch, ctc_cbo_stats_table_t *ctc_ bool is_part_table = stats->part_cnt ? true : false; stats->is_updated = req->stats->is_updated; stats->records = req->stats->records; + stats->page_size = req->stats->page_size; memcpy(stats->ndv_keys, req->stats->ndv_keys, stats->key_len); uint num_columns = req->stats->msg_len / sizeof(ctc_cbo_stats_column_t); if (!is_part_table) { *tch = req->tch; ctc_cbo_stats_table->estimate_rows = req->ctc_cbo_stats_table->estimate_rows; + ctc_cbo_stats_table->avg_row_len = req->ctc_cbo_stats_table->avg_row_len; + ctc_cbo_stats_table->blocks = req->ctc_cbo_stats_table->blocks; ctc_cbo_stats_columns_copy(ctc_cbo_stats_table->columns, req->ctc_cbo_stats_table->columns, stats, num_columns); } else { for (uint i = 0; i < req->num_part_fetch; i++) { ctc_cbo_stats_table[i].estimate_rows = req->ctc_cbo_stats_table[i].estimate_rows; + ctc_cbo_stats_table[i].avg_row_len = req->ctc_cbo_stats_table[i].avg_row_len; + ctc_cbo_stats_table[i].blocks = req->ctc_cbo_stats_table[i].blocks; ctc_cbo_stats_columns_copy(ctc_cbo_stats_table[i].columns, req->ctc_cbo_stats_table[i].columns, stats, num_columns); } diff --git a/storage/ctc/ha_ctc.cc b/storage/ctc/ha_ctc.cc index bbacc67..012cc86 100644 --- a/storage/ctc/ha_ctc.cc +++ b/storage/ctc/ha_ctc.cc @@ -3381,6 +3381,41 @@ EXTER_ATTACK int ha_ctc::rnd_pos(uchar *buf, uchar *pos) { return ret; } +double ha_ctc::scan_time() { + DBUG_TRACE; + double data_page_num = 1.0; + if (m_share && m_share->cbo_stats != nullptr) { + data_page_num = m_share->cbo_stats->ctc_cbo_stats_table->blocks; + } + return data_page_num; +} + +double ha_ctc::index_only_read_time(uint keynr, double records) { + double index_read_time; + uint32_t keys_per_block = (stats.block_size / 2 / + (table_share->key_info[keynr].key_length + ref_length) + 1); + index_read_time = ((double)(records + keys_per_block - 1) / (double)keys_per_block); + return index_read_time; +} + +double ha_ctc::read_time(uint index, uint ranges, ha_rows rows) { + DBUG_TRACE; + if (index != table->s->primary_key) { + return (handler::read_time(index, ranges, rows)); + } + + if (rows <= 2) { + return ((double)rows); + } + + double time_for_scan = scan_time(); + if (stats.records < rows) { + return (time_for_scan); + } + + return (ranges + (double)rows / (double)stats.records * time_for_scan); +} + /** @brief ::info() is used to return information to the optimizer. See my_base.h for @@ -3423,6 +3458,8 @@ EXTER_ATTACK int ha_ctc::rnd_pos(uchar *buf, uchar *pos) { void ha_ctc::info_low() { if (m_share && m_share->cbo_stats != nullptr) { stats.records = m_share->cbo_stats->ctc_cbo_stats_table->estimate_rows; + stats.mean_rec_length = m_share->cbo_stats->ctc_cbo_stats_table->avg_row_len; + stats.block_size = m_share->cbo_stats->page_size; } } @@ -5565,7 +5602,7 @@ int ha_ctc::initialize_cbo_stats() END_RECORD_STATS(EVENT_TYPE_INITIALIZE_DBO) return ERR_ALLOC_MEMORY; } - *m_share->cbo_stats = {0, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr}; + *m_share->cbo_stats = {0, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr, 0}; m_share->cbo_stats->ctc_cbo_stats_table = (ctc_cbo_stats_table_t*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(ctc_cbo_stats_table_t), MYF(MY_WME)); if (m_share->cbo_stats->ctc_cbo_stats_table == nullptr) { @@ -5573,6 +5610,9 @@ int ha_ctc::initialize_cbo_stats() END_RECORD_STATS(EVENT_TYPE_INITIALIZE_DBO) return ERR_ALLOC_MEMORY; } + m_share->cbo_stats->ctc_cbo_stats_table->estimate_rows = 0; + m_share->cbo_stats->ctc_cbo_stats_table->avg_row_len = 0; + m_share->cbo_stats->ctc_cbo_stats_table->blocks = 0; m_share->cbo_stats->ctc_cbo_stats_table->columns = (ctc_cbo_stats_column_t*)my_malloc(PSI_NOT_INSTRUMENTED, table->s->fields * sizeof(ctc_cbo_stats_column_t), MYF(MY_WME)); if (m_share->cbo_stats->ctc_cbo_stats_table->columns == nullptr) { diff --git a/storage/ctc/ha_ctc.h b/storage/ctc/ha_ctc.h index d5130c9..fce2752 100644 --- a/storage/ctc/ha_ctc.h +++ b/storage/ctc/ha_ctc.h @@ -447,43 +447,24 @@ public: uint max_supported_key_part_length( HA_CREATE_INFO *create_info) const override; - /** @brief - Called in test_quick_select to determine if indexes should be used. + /** + @brief Called in test_quick_select to determine if indexes should be used. + we assume that the data pages is equal to the disk scans times. + @return How many seeks it will take to read through the whole table. */ - virtual double scan_time() override { - DBUG_TRACE; - return (ulonglong)(stats.records + stats.deleted) / 100 + 2; - } + double scan_time() override; - /** @brief - This method will never be called if you do not implement indexes. + /** + @brief This method will never be called if you do not implement indexes. + @return estimated cost of 'index only' scan */ - virtual double read_time( - uint index, /*!< in: key number */ - uint ranges, /*!< in: how many ranges */ - ha_rows rows) /*!< in: estimated number of rows in the ranges */ override { - DBUG_TRACE; - - if (index != table->s->primary_key) { - /* Not clustered */ - return (handler::read_time(index, ranges, rows)); - } + virtual double index_only_read_time(uint keynr, double records) override; - if (rows <= 2) { - return ((double)rows); - } - - /* Assume that the read time is proportional to the scan time for all - rows + at most one seek per range. */ - - double time_for_scan = scan_time(); - - if (stats.records < rows) { - return (time_for_scan); - } - - return (ranges + (double)rows / (double)stats.records * time_for_scan); - } + /** + @brief This method will never be called if you do not implement indexes. + @return estimated time measured in disk seeks + */ + double read_time(uint index, uint ranges, ha_rows rows) override; bool inplace_alter_table( TABLE *altered_table MY_ATTRIBUTE((unused)), diff --git a/storage/ctc/ha_ctcpart.cc b/storage/ctc/ha_ctcpart.cc index aef0003..7ed0db6 100644 --- a/storage/ctc/ha_ctcpart.cc +++ b/storage/ctc/ha_ctcpart.cc @@ -818,14 +818,41 @@ enum row_type ha_ctcpart::get_partition_row_type(const dd::Table *partition_tabl return ROW_TYPE_NOT_USED; } +double ha_ctcpart::scan_time() { + DBUG_TRACE; + double sum_data_page = 0.0; + + if (m_part_share != nullptr && m_part_share->cbo_stats != nullptr) { + uint part_num = m_is_sub_partitioned ? table->part_info->num_parts * table->part_info->num_subparts : + table->part_info->num_parts; + for (uint i = m_part_info->get_first_used_partition(); i < part_num; + i = m_part_info->get_next_used_partition(i)) { + sum_data_page += m_part_share->cbo_stats->ctc_cbo_stats_table[i].blocks; + } + } + return sum_data_page; +} + void ha_ctcpart::info_low() { stats.records = 0; + uint total_row_len = 0; if (m_part_share->cbo_stats != nullptr) { - uint part_num = m_is_sub_partitioned ? table->part_info->num_parts * table->part_info->num_subparts : + uint total_part_num = m_is_sub_partitioned ? table->part_info->num_parts * table->part_info->num_subparts : table->part_info->num_parts; - for (uint part_id = m_part_info->get_first_used_partition(); part_id < part_num; + uint curr_part_num = 0; + stats.block_size = m_part_share->cbo_stats->page_size; + + for (uint part_id = m_part_info->get_first_used_partition(); part_id < total_part_num; part_id = m_part_info->get_next_used_partition(part_id)) { stats.records += m_part_share->cbo_stats->ctc_cbo_stats_table[part_id].estimate_rows; + if (m_part_share->cbo_stats->ctc_cbo_stats_table[part_id].avg_row_len != 0) { + total_row_len += m_part_share->cbo_stats->ctc_cbo_stats_table[part_id].avg_row_len; + curr_part_num++; + } + } + + if (curr_part_num > 0) { + stats.mean_rec_length = total_row_len / curr_part_num; } } } @@ -1012,7 +1039,7 @@ int ha_ctcpart::initialize_cbo_stats() { ctc_log_error("alloc mem failed, m_part_share->cbo_stats size(%lu)", sizeof(ctc_cbo_stats_t)); return ERR_ALLOC_MEMORY; } - *m_part_share->cbo_stats = {0, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr}; + *m_part_share->cbo_stats = {0, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr, 0}; m_part_share->cbo_stats->part_cnt = part_num; @@ -1030,6 +1057,8 @@ int ha_ctcpart::initialize_cbo_stats() { } for (uint i = 0; i < part_num; i++) { m_part_share->cbo_stats->ctc_cbo_stats_table[i].estimate_rows = 0; + m_part_share->cbo_stats->ctc_cbo_stats_table[i].avg_row_len = 0; + m_part_share->cbo_stats->ctc_cbo_stats_table[i].blocks = 0; m_part_share->cbo_stats->ctc_cbo_stats_table[i].columns = (ctc_cbo_stats_column_t*)my_malloc(PSI_NOT_INSTRUMENTED, table->s->fields * sizeof(ctc_cbo_stats_column_t), MYF(MY_WME)); if (m_part_share->cbo_stats->ctc_cbo_stats_table[i].columns == nullptr) { diff --git a/storage/ctc/ha_ctcpart.h b/storage/ctc/ha_ctcpart.h index a42c4f9..863769f 100644 --- a/storage/ctc/ha_ctcpart.h +++ b/storage/ctc/ha_ctcpart.h @@ -392,6 +392,8 @@ class ha_ctcpart : public ha_ctc, bool equal_range_on_part_field(const key_range *start_key, const key_range *end_key); + double scan_time() override; + void info_low() override; int info(uint) override; -- Gitee