221 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			221 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * Copyright (c) 2021 OceanBase
 | |
|  * OceanBase CE is licensed under Mulan PubL v2.
 | |
|  * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | |
|  * You may obtain a copy of Mulan PubL v2 at:
 | |
|  *          http://license.coscl.org.cn/MulanPubL-2.0
 | |
|  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | |
|  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | |
|  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | |
|  * See the Mulan PubL v2 for more details.
 | |
|  */
 | |
| 
 | |
| #define USING_LOG_PREFIX SQL_OPT
 | |
| #include "ob_storage_estimator.h"
 | |
| #include "lib/worker.h"
 | |
| #include "storage/tx_storage/ob_access_service.h"
 | |
| #include "storage/access/ob_table_scan_range.h"
 | |
| #include "share/ob_simple_batch.h"
 | |
| #include "storage/access/ob_dml_param.h"
 | |
| 
 | |
| namespace oceanbase {
 | |
| using namespace storage;
 | |
| using namespace share;
 | |
| 
 | |
| namespace sql {
 | |
| 
 | |
| int ObStorageEstimator::estimate_row_count(const obrpc::ObEstPartArg &arg,
 | |
|                                            obrpc::ObEstPartRes &res)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   //est path rows
 | |
|   ObTableScanParam param;
 | |
|   param.schema_version_ = arg.schema_version_;
 | |
|   for (int64_t i = 0; OB_SUCC(ret) && i < arg.index_params_.count(); i++) {
 | |
|     obrpc::ObEstPartResElement est_res;
 | |
|     param.index_id_ = arg.index_params_.at(i).index_id_;
 | |
|     param.scan_flag_ = arg.index_params_.at(i).scan_flag_;
 | |
|     param.tablet_id_ = arg.index_params_.at(i).tablet_id_;
 | |
|     param.ls_id_ = arg.index_params_.at(i).ls_id_;
 | |
|     param.tx_id_ = arg.index_params_.at(i).tx_id_;
 | |
|     if (OB_FAIL(storage_estimate_rowcount(
 | |
|                   arg.index_params_.at(i).tenant_id_,
 | |
|                   param,
 | |
|                   arg.index_params_.at(i).batch_,
 | |
|                   est_res))) {
 | |
|       LOG_WARN("failed to estimate index row count", K(ret));
 | |
|     } else if (OB_FAIL(res.index_param_res_.push_back(est_res))) {
 | |
|       LOG_WARN("failed to push back result", K(ret));
 | |
|     } else {
 | |
|       LOG_TRACE("[OPT EST]: row count stat", K(est_res), K(i), K(param));
 | |
|     }
 | |
|   }
 | |
| #if !defined(NDEBUG)
 | |
|   if (OB_SUCC(ret)) {
 | |
|     LOG_INFO("[OPT EST] rowcount estimation result", K(arg), K(res));
 | |
|   }
 | |
| #endif
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int ObStorageEstimator::estimate_block_count_and_row_count(const obrpc::ObEstBlockArg &arg,
 | |
|                                                            obrpc::ObEstBlockRes &res)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   for (int64_t i = 0; OB_SUCC(ret) && i < arg.tablet_params_arg_.count(); ++i) {
 | |
|     obrpc::ObEstBlockResElement est_res;
 | |
|     if (OB_FAIL(storage_estimate_block_count_and_row_count(arg.tablet_params_arg_.at(i), est_res))) {
 | |
|       LOG_WARN("failed to estimate tablet block count and row count", K(ret));
 | |
|     } else if (OB_FAIL(res.tablet_params_res_.push_back(est_res))) {
 | |
|       LOG_WARN("failed to push back result", K(ret));
 | |
|     } else {
 | |
|       LOG_TRACE("[OPT EST]: block count and row count stat", K(est_res), K(i), "param", arg.tablet_params_arg_.at(i));
 | |
|     }
 | |
|   }
 | |
| #if !defined(NDEBUG)
 | |
|   if (OB_SUCC(ret)) {
 | |
|     LOG_INFO("[OPT EST] block count and row count estimation result", K(arg), K(res));
 | |
|   }
 | |
| #endif
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| // estimate scan rowcount
 | |
| int ObStorageEstimator::storage_estimate_rowcount(const uint64_t tenant_id,
 | |
|                                                   const ObTableScanParam ¶m,
 | |
|                                                   const ObSimpleBatch &batch,
 | |
|                                                   obrpc::ObEstPartResElement &res)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   double rc_logical = 0;
 | |
|   double rc_physical = 0;
 | |
|   if (!batch.is_valid()) {
 | |
|     // do nothing when there is no scan range
 | |
|     res.logical_row_count_ = static_cast<int64_t>(rc_logical);
 | |
|     res.physical_row_count_ = static_cast<int64_t>(rc_physical);
 | |
|     res.reliable_ = true;
 | |
|   } else if (OB_FAIL(storage_estimate_partition_batch_rowcount(
 | |
|                        tenant_id,
 | |
|                        batch,
 | |
|                        param,
 | |
|                        res.est_records_,
 | |
|                        rc_logical,
 | |
|                        rc_physical))) {
 | |
|     LOG_WARN("fail to get partition batch rowcount", K(param.tablet_id_), K(batch), K(ret));
 | |
|     res.reset();
 | |
|     ret = OB_SUCCESS;
 | |
|   } else {
 | |
|     res.logical_row_count_ = static_cast<int64_t>(rc_logical);
 | |
|     res.physical_row_count_ = static_cast<int64_t>(rc_physical);
 | |
|     res.reliable_ = true;
 | |
|   }
 | |
|   LOG_TRACE("[OPT EST]:estimate partition scan batch rowcount", K(res), K(batch), K(ret));
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| //@shanyan.g 调整层按照parition级别来操作
 | |
| int ObStorageEstimator::storage_estimate_partition_batch_rowcount(
 | |
|     const uint64_t tenant_id,
 | |
|     const ObSimpleBatch &batch,
 | |
|     const storage::ObTableScanParam &table_scan_param,
 | |
|     ObIArray<ObEstRowCountRecord> &est_records,
 | |
|     double &logical_row_count,
 | |
|     double &physical_row_count)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   MTL_SWITCH(tenant_id) {
 | |
|     int64_t rc_logical = 0;
 | |
|     int64_t rc_physical = 0;
 | |
|     ObArenaAllocator allocator;
 | |
|     const int64_t timeout_us = THIS_WORKER.get_timeout_remain();
 | |
|     ObAccessService *access_service = NULL;
 | |
|     storage::ObTableScanRange table_scan_range;
 | |
|     if (OB_ISNULL(access_service = MTL(ObAccessService *))) {
 | |
|       ret = OB_ERR_UNEXPECTED;
 | |
|       LOG_WARN("get unexpected null", K(ret), K(access_service));
 | |
|     } else if (OB_FAIL(table_scan_range.init(batch, allocator))) {
 | |
|       STORAGE_LOG(WARN, "Failed to init table scan range", K(ret), K(batch));
 | |
|     } else if (OB_FAIL(access_service->estimate_row_count(table_scan_param,
 | |
|                                                           table_scan_range,
 | |
|                                                           timeout_us,
 | |
|                                                           est_records,
 | |
|                                                           rc_logical,
 | |
|                                                           rc_physical))) {
 | |
|       LOG_TRACE("OPT:[STORAGE EST FAILED, USE STAT EST]", "storage_ret", ret);
 | |
|     } else {
 | |
|       LOG_TRACE("storage estimate row count result", K(rc_logical), K(rc_physical),
 | |
|                 K(table_scan_param), K(table_scan_range), K(timeout_us), K(ret));
 | |
|         logical_row_count = rc_logical < 0 ? 1.0 : static_cast<double>(rc_logical);
 | |
|         physical_row_count = rc_physical < 0 ? 1.0 : static_cast<double>(rc_physical);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int ObStorageEstimator::storage_estimate_block_count_and_row_count(
 | |
|     const obrpc::ObEstBlockArgElement &arg,
 | |
|     obrpc::ObEstBlockResElement &res)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   int64_t macro_block_count = 0;
 | |
|   int64_t micro_block_count = 0;
 | |
|   int64_t sstable_row_count = 0;
 | |
|   int64_t memtable_row_count = 0;
 | |
|   common::ObIArray<int64_t> &cg_macro_cnt_arr = res.cg_macro_cnt_arr_;
 | |
|   common::ObIArray<int64_t> &cg_micro_cnt_arr = res.cg_micro_cnt_arr_;
 | |
|   int64_t cg_count = arg.column_group_ids_.count();
 | |
|   LOG_TRACE("begin to storage estimate blockcount", K(arg));
 | |
| 
 | |
|   if (!arg.is_valid()) {
 | |
|     res.macro_block_count_ = macro_block_count;
 | |
|     res.micro_block_count_ = micro_block_count;
 | |
|     res.sstable_row_count_ = sstable_row_count;
 | |
|     res.memtable_row_count_ = memtable_row_count;
 | |
|   } else {
 | |
|     const uint64_t tenant_id = arg.tenant_id_;
 | |
|     MTL_SWITCH(tenant_id) {
 | |
|       const int64_t timeout_us = THIS_WORKER.get_timeout_remain();
 | |
|       ObAccessService *access_service = NULL;
 | |
|       if (OB_ISNULL(access_service = MTL(ObAccessService *))) {
 | |
|         ret = OB_ERR_UNEXPECTED;
 | |
|         LOG_WARN("get unexpected null", K(ret), K(access_service));
 | |
|       } else if (OB_FAIL(access_service->estimate_block_count_and_row_count(arg.ls_id_,
 | |
|                                                                             arg.tablet_id_,
 | |
|                                                                             timeout_us,
 | |
|                                                                             macro_block_count,
 | |
|                                                                             micro_block_count,
 | |
|                                                                             sstable_row_count,
 | |
|                                                                             memtable_row_count,
 | |
|                                                                             cg_macro_cnt_arr,
 | |
|                                                                             cg_micro_cnt_arr))) {
 | |
|         LOG_WARN("OPT:[STORAGE EST BLOCK COUNT FAILED]", "storage_ret", ret);
 | |
|       } else if (OB_UNLIKELY(cg_count != 0 &&
 | |
|                              (cg_macro_cnt_arr.count() > cg_count
 | |
|                               || cg_micro_cnt_arr.count() > cg_count
 | |
|                               || cg_macro_cnt_arr.count() != cg_micro_cnt_arr.count()))) {
 | |
|         ret = OB_ERR_UNEXPECTED;
 | |
|         LOG_WARN("unexpected cg count", K(ret), K(cg_macro_cnt_arr.count()), K(cg_micro_cnt_arr.count()), K(arg.column_group_ids_.count()));
 | |
|       } else {
 | |
|         LOG_TRACE("storage estimate block count and row count result", K(macro_block_count),
 | |
|                 K(micro_block_count), K(sstable_row_count), K(memtable_row_count), K(ret));
 | |
|         res.macro_block_count_ = macro_block_count;
 | |
|         res.micro_block_count_ = micro_block_count;
 | |
|         res.sstable_row_count_ = sstable_row_count;
 | |
|         res.memtable_row_count_ = memtable_row_count;
 | |
|         for (int64_t i = cg_macro_cnt_arr.count(); OB_SUCC(ret) && i < cg_count; i++) {
 | |
|           if (OB_FAIL(cg_macro_cnt_arr.push_back(0))) {
 | |
|             LOG_WARN("fail to push macro count", K(ret));
 | |
|           } else if (OB_FAIL(cg_micro_cnt_arr.push_back(0))) {
 | |
|             LOG_WARN("fail to push micro count", K(ret));
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| } // end of sql
 | |
| } // end of oceanbase
 | 
