diff --git a/mysql-test/suite/ctc/r/ctc_bit_analyze.result b/mysql-test/suite/ctc/r/ctc_bit_analyze.result index 7d18c30ad10d8f8f6871520c82bc73360c0af50a..fccc1c3ad289360fe538761e5ae716d64a2b0b8c 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 48045acb2487bc3b3421b01f9f9e835b18d3f53b..1b01fc21c66386f30e44b20f72baa3993cfa1759 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 ad2f03b94204fc825e9981f5e1ff3c10172e72e1..c4518f4bd1324e80fbcfd102298c21bb4b0b41df 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 bbacc675d75205e03d174b48508fac390305b895..012cc869aebcb15fbf87cffb0b59111c901b6fad 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 d5130c90f213524c2659bb6197064548795b53a4..fce2752791c9210d12d3cb83968931d9120b27ae 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 aef0003571f7ffd532621f3b1adcb1c2712c20dc..7ed0db68306f00efaab237befa61f6e9e976f55e 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 a42c4f90b6cfc7d6ceb269ba4ca7b1b1b9920938..863769ff4eb20cfd5c51054efb7411e4f0611586 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;