[FEAT MERGE] skip scan feature and performance optimization

This commit is contained in:
obdev 2023-01-04 09:08:22 +00:00 committed by ob-robot
parent ad415b4359
commit 07b1224a51
119 changed files with 6176 additions and 2010 deletions

View File

@ -390,6 +390,7 @@ void TestIndexBlockDataPrepare::prepare_data()
index_desc.schema_version_ = 10;
ASSERT_TRUE(index_desc.is_valid());
ASSERT_EQ(OB_SUCCESS, root_index_builder_->init(index_desc));
root_index_builder_->index_store_desc_.need_pre_warm_ = false; // close index block pre warm
ASSERT_EQ(OB_SUCCESS, writer.open(desc, start_seq));
ASSERT_EQ(OB_SUCCESS, row_generate_.init(table_schema_, &allocator_));

3
src/objit/include/objit/common/ob_item_type.h Normal file → Executable file
View File

@ -1206,6 +1206,9 @@ typedef enum ObItemType
T_FULL_HINT,
T_USE_DAS_HINT,
T_NO_USE_DAS_HINT,
T_INDEX_SS_HINT,
T_INDEX_SS_ASC_HINT,
T_INDEX_SS_DESC_HINT,
T_USE_MERGE,
T_USE_HASH,
T_NO_USE_HASH,

View File

@ -162,6 +162,7 @@ ob_set_subtarget(ob_server virtual_table
virtual_table/ob_all_virtual_files_table.cpp
virtual_table/ob_all_virtual_id_service.cpp
virtual_table/ob_all_virtual_io_stat.cpp
virtual_table/ob_all_virtual_kvcache_store_memblock.cpp
virtual_table/ob_all_virtual_load_data_stat.cpp
virtual_table/ob_all_virtual_lock_wait_stat.cpp
virtual_table/ob_all_virtual_long_ops_status.cpp

View File

@ -0,0 +1,200 @@
// Copyright (c) 2022 OceanBase
// Authors:
// lvling <zhaoruizhe.zrz@oceanbase.com>
// OceanBase 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.
#include "observer/virtual_table/ob_all_virtual_kvcache_store_memblock.h"
namespace oceanbase
{
namespace observer
{
ObAllVirtualKVCacheStoreMemblock::ObAllVirtualKVCacheStoreMemblock()
: ObVirtualTableScannerIterator(),
memblock_iter_(0),
addr_(nullptr),
ipstr_(),
port_(0),
memblock_infos_(),
str_buf_()
{
}
ObAllVirtualKVCacheStoreMemblock::~ObAllVirtualKVCacheStoreMemblock()
{
reset();
}
void ObAllVirtualKVCacheStoreMemblock::reset()
{
ObVirtualTableScannerIterator::reset();
memblock_iter_ = 0;
addr_ = nullptr;
port_ = 0;
ipstr_.reset();
str_buf_.reset();
memblock_infos_.reset();
}
int ObAllVirtualKVCacheStoreMemblock::inner_get_next_row(ObNewRow *&row)
{
int ret = OB_SUCCESS;
row = nullptr;
if (OB_UNLIKELY(NULL == allocator_)) {
ret = OB_NOT_INIT;
SERVER_LOG(WARN, "allocator is NULL", K(ret));
} else if (memblock_iter_ >= memblock_infos_.count()) {
ret = OB_ITER_END;
} else if (OB_FAIL(process_row(memblock_infos_.at(memblock_iter_++)))) {
SERVER_LOG(WARN, "Fail to process current row", K(ret), K(memblock_iter_));
} else {
row = &cur_row_;
}
return ret;
}
int ObAllVirtualKVCacheStoreMemblock::set_ip()
{
int ret = OB_SUCCESS;
char ipbuf[common::OB_IP_STR_BUFF];
if (nullptr == addr_) {
ret = OB_ENTRY_NOT_EXIST;
SERVER_LOG(WARN, "Null address", K(ret), KP(addr_));
} else if (!addr_->ip_to_string(ipbuf, sizeof(ipbuf))) {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(ERROR, "Fail to cast ip to string", K(ret));
} else {
ipstr_ = ObString::make_string(ipbuf);
port_ = addr_->get_port();
if (OB_FAIL(ob_write_string(*allocator_, ipstr_, ipstr_))) {
SERVER_LOG(WARN, "Failed to write string", K(ret));
}
}
return ret;
}
int ObAllVirtualKVCacheStoreMemblock::inner_open()
{
int ret = OB_SUCCESS;
memblock_infos_.reset();
if (OB_FAIL(set_ip())) {
SERVER_LOG(WARN, "Fail to get ip in ObAllVirtualKVCacheStoreMemblock", K(ret));
} else if (OB_FAIL(ObKVGlobalCache::get_instance().get_memblock_info(effective_tenant_id_, memblock_infos_))) { // get memblock info from kvcache
SERVER_LOG(WARN, "Fail to get memblock information from global cache", K(ret));
}
return ret;
}
int ObAllVirtualKVCacheStoreMemblock::process_row(const ObKVCacheStoreMemblockInfo &info)
{
int ret = OB_SUCCESS;
if (!info.is_valid()) {
ret = OB_INVALID_ARGUMENT;
SERVER_LOG(WARN, "Invalid argument", K(ret), K(info));
} else {
cur_row_.count_ = reserved_column_cnt_;
for (int64_t cell_idx = 0 ; OB_SUCC(ret) && cell_idx < output_column_ids_.count() ; ++cell_idx) {
uint64_t col_id = output_column_ids_.at(cell_idx);
switch (col_id) {
case SVR_IP : {
cur_row_.cells_[cell_idx].set_varchar(ipstr_);
cur_row_.cells_[cell_idx].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
break;
}
case SVR_PORT : {
cur_row_.cells_[cell_idx].set_int(port_);
break;
}
case TENANT_ID : {
cur_row_.cells_[cell_idx].set_int(info.tenant_id_);
break;
}
case CACHE_ID : {
cur_row_.cells_[cell_idx].set_int(info.cache_id_);
break;
}
case CACHE_NAME : {
cur_row_.cells_[cell_idx].set_varchar(info.cache_name_);
cur_row_.cells_[cell_idx].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
break;
}
case MEMBLOCK_PTR : {
cur_row_.cells_[cell_idx].set_varchar(info.memblock_ptr_);
cur_row_.cells_[cell_idx].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
break;
}
case REF_COUNT : {
cur_row_.cells_[cell_idx].set_int(info.ref_count_);
break;
}
case STATUS : {
cur_row_.cells_[cell_idx].set_int(info.using_status_);
break;
}
case POLICY : {
cur_row_.cells_[cell_idx].set_int(info.policy_);
break;
}
case KV_CNT : {
cur_row_.cells_[cell_idx].set_int(info.kv_cnt_);
break;
}
case GET_CNT : {
cur_row_.cells_[cell_idx].set_int(info.get_cnt_);
break;
}
case RECENT_GET_CNT : {
cur_row_.cells_[cell_idx].set_int(info.recent_get_cnt_);
break;
}
case PRIORITY : {
cur_row_.cells_[cell_idx].set_int(info.priority_);
break;
}
case SCORE : {
static const int64_t MAX_DOUBLE_PRINT_SIZE = 64;
char buf[MAX_DOUBLE_PRINT_SIZE];
memset(buf, 0, MAX_DOUBLE_PRINT_SIZE);
str_buf_.reset();
number::ObNumber num;
double value = info.score_;
if (OB_UNLIKELY(0 > snprintf(buf, MAX_DOUBLE_PRINT_SIZE, "%lf", value))) {
ret = OB_IO_ERROR;
SERVER_LOG(WARN, "snprintf fail", K(ret), K(errno), KERRNOMSG(errno));
} else if (OB_FAIL(num.from(buf, str_buf_))) {
SERVER_LOG(WARN, "Fail to cast to number", K(ret), K(cell_idx), K(output_column_ids_), K(col_id));
} else {
cur_row_.cells_[cell_idx].set_number(num);
}
break;
}
case ALIGN_SIZE : {
cur_row_.cells_[cell_idx].set_int(info.align_size_);
break;
}
default : {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "Invalid column id", K(ret), K(cell_idx), K(col_id), K(output_column_ids_));
break;
}
}
}
}
return ret;
}
} // observer
} // oceanbase

View File

@ -0,0 +1,66 @@
// Copyright (c) 2022 OceanBase
// Authors:
// lvling <zhaoruizhe.zrz@oceanbase.com>
// OceanBase 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.
#ifndef OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_H_
#define OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_H_
#include "share/ob_virtual_table_scanner_iterator.h"
#include "share/cache/ob_kv_storecache.h"
namespace oceanbase
{
namespace observer
{
class ObAllVirtualKVCacheStoreMemblock : public common::ObVirtualTableScannerIterator
{
public:
ObAllVirtualKVCacheStoreMemblock();
virtual ~ObAllVirtualKVCacheStoreMemblock();
virtual void reset();
OB_INLINE void set_addr(common::ObAddr &addr) {addr_ = &addr;}
virtual int inner_get_next_row(common::ObNewRow *&row);
private:
virtual int set_ip();
virtual int inner_open() override;
int process_row(const ObKVCacheStoreMemblockInfo &info);
private:
enum CACHE_COLUMN
{
SVR_IP = common::OB_APP_MIN_COLUMN_ID,
SVR_PORT,
TENANT_ID,
CACHE_ID,
CACHE_NAME,
MEMBLOCK_PTR,
REF_COUNT,
STATUS,
POLICY,
KV_CNT,
GET_CNT,
RECENT_GET_CNT,
PRIORITY,
SCORE,
ALIGN_SIZE
};
int64_t memblock_iter_;
common::ObAddr *addr_;
common::ObString ipstr_;
int32_t port_;
ObSEArray<ObKVCacheStoreMemblockInfo, 1024> memblock_infos_;
common::ObStringBuf str_buf_;
DISALLOW_COPY_AND_ASSIGN(ObAllVirtualKVCacheStoreMemblock);
};
} // observer
} // oceanbase
#endif // OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_H_

View File

@ -396,7 +396,7 @@ int ObAllVirtualSysStat::get_cache_size_(const int64_t tenant_id, ObStatEventSet
{
int ret = OB_SUCCESS;
ObArray<ObKVCacheInstHandle> inst_handles;
if (OB_FAIL(ObKVGlobalCache::get_instance().get_tenant_cache_info(tenant_id, inst_handles))) {
if (OB_FAIL(ObKVGlobalCache::get_instance().get_cache_inst_info(tenant_id, inst_handles))) {
SERVER_LOG(WARN, "Fail to get tenant cache infos, ", K(ret));
} else {
ObKVCacheInst * inst = NULL;

View File

@ -27,6 +27,7 @@ ObInfoSchemaKvCacheTable::ObInfoSchemaKvCacheTable()
cache_iter_(0),
str_buf_(),
arenallocator_(),
tenant_di_info_(),
tenant_dis_()
{
}
@ -49,241 +50,263 @@ void ObInfoSchemaKvCacheTable::reset()
cells_[i].reset();
}
arenallocator_.reset();
tenant_di_info_.reset();
tenant_dis_.reset();
}
int ObInfoSchemaKvCacheTable::set_ip(common::ObAddr *addr)
int ObInfoSchemaKvCacheTable::inner_get_next_row(ObNewRow *&row)
{
int ret = OB_SUCCESS;
row = nullptr;
ObKVCacheInst * inst = NULL;
ObDiagnoseTenantInfo *tenant_info = nullptr;
if (OB_UNLIKELY(NULL == allocator_)) {
ret = OB_NOT_INIT;
SERVER_LOG(WARN, "Invalid allocator, not init", K(ret), KP(allocator_));
} else if (OB_FAIL(get_handles(inst, tenant_info))) {
if (OB_ITER_END != ret) {
SERVER_LOG(WARN, "Fail to get cache inst or tenant diagnose info", K(ret));
}
} else if (OB_FAIL(set_diagnose_info(inst, tenant_info))) {
SERVER_LOG(WARN, "Fail to set diagnose info for cache inst", K(ret));
} else if (OB_FAIL(process_row(inst))) {
SERVER_LOG(WARN, "Fail to process current row", K(ret));
} else {
row = &cur_row_;
}
return ret;
}
int ObInfoSchemaKvCacheTable::set_ip()
{
int ret = OB_SUCCESS;
char ipbuf[common::OB_IP_STR_BUFF];
if (NULL == addr){
if (nullptr == addr_) {
ret = OB_ENTRY_NOT_EXIST;
SERVER_LOG(WARN, "Null address", K(ret), KP(addr_));
} else if (!addr_->ip_to_string(ipbuf, sizeof(ipbuf))) {
SERVER_LOG(ERROR, "ip to string failed");
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(ERROR, "Fail to cast ip to string", K(ret));
} else {
ipstr_ = ObString::make_string(ipbuf);
if (OB_FAIL(ob_write_string(*allocator_, ipstr_, ipstr_))) {
SERVER_LOG(WARN, "failed to write string", K(ret));
SERVER_LOG(WARN, "Failed to write string", K(ret));
}
port_ = addr_->get_port();
}
return ret;
}
int ObInfoSchemaKvCacheTable::inner_get_next_row(ObNewRow *&row)
int ObInfoSchemaKvCacheTable::inner_open()
{
int ret = OB_SUCCESS;
static const int64_t MAX_DOUBLE_PRINT_SIZE = 64;
if (OB_UNLIKELY(NULL == allocator_)) {
ret = OB_NOT_INIT;
SERVER_LOG(WARN, "allocator is NULL", K(ret));
} else {
ObKVCacheInst * inst = NULL;
const int64_t col_count = output_column_ids_.count();
cur_row_.cells_ = cells_;
cur_row_.count_ = reserved_column_cnt_;
if (0 == cache_iter_) {
inst_handles_.reuse();
if (OB_SUCCESS != (ret = set_ip(addr_))){
SERVER_LOG(WARN, "can't get ip", K(ret));
} else if (is_sys_tenant(effective_tenant_id_)) {
// sys tenant show all tenant infos
if (OB_FAIL(ObKVGlobalCache::get_instance().get_all_cache_info(inst_handles_))) {
SERVER_LOG(WARN, "Fail to get all cache info, ", K(ret));
}
} else {
// user tenant show user tenant infos
if (OB_FAIL(ObKVGlobalCache::get_instance().get_tenant_cache_info(effective_tenant_id_, inst_handles_))) {
SERVER_LOG(WARN, "Fail to get tenant cache info", KR(ret), K(effective_tenant_id_));
}
}
if(OB_SUCC(ret) && oceanbase::lib::is_diagnose_info_enabled()) {
arenallocator_.reuse();
tenant_dis_.reuse();
if (is_sys_tenant(effective_tenant_id_)) {
if (OB_FAIL(ObDIGlobalTenantCache::get_instance().get_all_stat_event(arenallocator_, tenant_dis_))) {
SERVER_LOG(WARN, "Fail to get all_stat_event when diagnose_info_enabled, ", K(ret));
}
} else {
// TODO: by chaser.ch, add get tenant stat event interface
}
}
}
if (OB_SUCC(ret)) {
if (cache_iter_ >= inst_handles_.count()) {
ret = OB_ITER_END;
} else {
inst = inst_handles_.at(cache_iter_).get_inst();
if (OB_ISNULL(inst)) {
ret = OB_ERR_SYS;
SERVER_LOG(WARN, "kvcache inst should not be null", K(ret));
}
}
}
if(OB_SUCCESS == ret && oceanbase::lib::is_diagnose_info_enabled()) {
//use diagnose_info to set cache miss_cnt and hit_cnt
ObDiagnoseTenantInfo *tenant_info = NULL;
for (int64_t i = 0; i < tenant_dis_.count(); ++i) {
if (tenant_dis_.at(i).first == inst_handles_.at(cache_iter_).get_inst()->tenant_id_) {
tenant_info = tenant_dis_.at(i).second;
break;
}
}
if (OB_LIKELY(NULL != tenant_info && NULL != inst->status_.config_)) {
if( 0 == strcmp(inst->status_.config_->cache_name_,"user_block_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::BLOCK_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::BLOCK_CACHE_HIT));
} else if( 0 == strcmp(inst->status_.config_->cache_name_,"user_row_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::ROW_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::ROW_CACHE_HIT));
} else if( 0 == strcmp(inst->status_.config_->cache_name_,"bf_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::BLOOM_FILTER_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::BLOOM_FILTER_CACHE_HIT));
} else if( 0 == strcmp(inst->status_.config_->cache_name_,"fuse_row_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::FUSE_ROW_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::FUSE_ROW_CACHE_HIT));
} else if( 0 == strcmp(inst->status_.config_->cache_name_,"tablet_ls_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::TABLET_LS_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::TABLET_LS_CACHE_HIT));
} else if( 0 == strcmp(inst->status_.config_->cache_name_,"schema_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_CACHE_HIT));
} else if( 0 == strcmp(inst->status_.config_->cache_name_,"opt_table_stat_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::OPT_TABLE_STAT_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::OPT_TABLE_STAT_CACHE_HIT));
} else if( 0 == strcmp(inst->status_.config_->cache_name_,"opt_column_stat_cache")) {
inst->status_.total_miss_cnt_ =
GLOBAL_EVENT_GET(ObStatEventIds::OPT_COLUMN_STAT_CACHE_MISS);
inst->status_.total_hit_cnt_.set(
GLOBAL_EVENT_GET(ObStatEventIds::OPT_COLUMN_STAT_CACHE_HIT));
}
}
}
if (OB_SUCCESS == ret) {
str_buf_.reset();
uint64_t cell_idx = 0;
double value = 0;
char buf[MAX_DOUBLE_PRINT_SIZE];
memset(buf, 0, MAX_DOUBLE_PRINT_SIZE);
number::ObNumber num;
for (int64_t j = 0; OB_SUCC(ret) && j < col_count; ++j) {
uint64_t col_id = output_column_ids_.at(j);
switch(col_id) {
case TENANT_ID: {
cells_[cell_idx].set_int(inst->tenant_id_);
break;
}
case SVR_IP: {
cells_[cell_idx].set_varchar(ipstr_);
cells_[cell_idx].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
break;
}
case SVR_PORT: {
cells_[cell_idx].set_int(port_);
break;
}
case CACHE_NAME: {
if (NULL != inst->status_.config_) {
cells_[cell_idx].set_varchar(inst->status_.config_->cache_name_);
cells_[cell_idx].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
}
break;
}
case CACHE_ID: {
cells_[cell_idx].set_int(inst->cache_id_);
break;
}
case CACHE_SIZE: {
cells_[cell_idx].set_int(inst->status_.store_size_ + inst->status_.map_size_);
break;
}
case PRIORITY: {
if (NULL != inst->status_.config_) {
cells_[cell_idx].set_int(inst->status_.config_->priority_);
} else {
cells_[cell_idx].set_int(0);
}
break;
}
case CACHE_STORE_SIZE: {
cells_[cell_idx].set_int(inst->status_.store_size_);
break;
}
case CACHE_MAP_SIZE: {
cells_[cell_idx].set_int(inst->status_.map_size_);
break;
}
case KV_CNT: {
cells_[cell_idx].set_int(inst->status_.kv_cnt_);
break;
}
case HIT_RATIO: {
memset(buf, 0, MAX_DOUBLE_PRINT_SIZE);
value = inst->status_.get_hit_ratio() *100;
if (OB_UNLIKELY(0 > snprintf(buf, MAX_DOUBLE_PRINT_SIZE, "%lf", value))) {
ret = OB_IO_ERROR;
SERVER_LOG(WARN, "snprintf fail", K(ret), K(errno), KERRNOMSG(errno));
} else if (OB_SUCCESS == (ret = num.from(buf, str_buf_))) {
cells_[cell_idx].set_number(num);
}
break;
}
case TOTAL_PUT_CNT: {
cells_[cell_idx].set_int(inst->status_.total_put_cnt_.value());
break;
}
case TOTAL_HIT_CNT: {
cells_[cell_idx].set_int(inst->status_.total_hit_cnt_.value());
break;
}
case TOTAL_MISS_CNT: {
cells_[cell_idx].set_int(inst->status_.total_miss_cnt_);
break;
}
case HOLD_SIZE: {
cells_[cell_idx].set_int(inst->status_.hold_size_);
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "invalid column id", K(ret), K(cell_idx),
K(output_column_ids_), K(col_id));
break;
}
}
if (OB_SUCC(ret)) {
cell_idx++;
} else if (OB_ERR_UNEXPECTED != ret) {
SERVER_LOG(WARN, "failed cast to number", K(ret), K(cell_idx),
K(output_column_ids_), K(col_id));
}
}
}
if (OB_SUCC(ret)) {
cache_iter_++;
row = &cur_row_;
}
inst_handles_.reuse();
if (OB_FAIL(set_ip())) {
SERVER_LOG(WARN, "Fail to set ip from addr", K(ret), K(addr_));
} else if (OB_FAIL(ObKVGlobalCache::get_instance().get_cache_inst_info(effective_tenant_id_, inst_handles_))) {
SERVER_LOG(WARN, "Fail to get cache info", K(ret), K(effective_tenant_id_));
} else if (OB_FAIL(get_tenant_info())) {
SERVER_LOG(WARN, "Fail to get tenant info", K(ret));
}
return ret;
}
int ObInfoSchemaKvCacheTable::get_tenant_info()
{
int ret = OB_SUCCESS;
if (oceanbase::lib::is_diagnose_info_enabled()) {
if (is_sys_tenant(effective_tenant_id_)) {
arenallocator_.reuse();
tenant_dis_.reuse();
if (OB_FAIL(ObDIGlobalTenantCache::get_instance().get_all_stat_event(arenallocator_, tenant_dis_))) {
SERVER_LOG(WARN, "Fail to get all stat event", K(ret));
}
} else {
tenant_di_info_.reset();
if (OB_FAIL(ObDIGlobalTenantCache::get_instance().get_the_diag_info(effective_tenant_id_, tenant_di_info_))) {
SERVER_LOG(WARN, "Fail to get tenant stat event", K(ret), K(effective_tenant_id_));
}
}
}
return ret;
}
int ObInfoSchemaKvCacheTable::get_handles(ObKVCacheInst *&inst, ObDiagnoseTenantInfo *&tenant_info)
{
int ret = OB_SUCCESS;
inst = nullptr;
tenant_info = nullptr;
if (cache_iter_ >= inst_handles_.count()) {
ret = OB_ITER_END;
} else {
inst = inst_handles_.at(cache_iter_++).get_inst();
}
if (OB_FAIL(ret)) {
} else if (!oceanbase::lib::is_diagnose_info_enabled()) {
} else if (is_sys_tenant(effective_tenant_id_)) {
for (int64_t i = 0 ; i < tenant_dis_.count() ; ++i) {
if (tenant_dis_.at(i).first == inst->tenant_id_) {
tenant_info = tenant_dis_.at(i).second;
break;
}
}
} else {
tenant_info = &tenant_di_info_;
}
return ret;
}
int ObInfoSchemaKvCacheTable::set_diagnose_info(ObKVCacheInst *inst, ObDiagnoseTenantInfo *tenant_info)
{
int ret = OB_SUCCESS;
if (!oceanbase::lib::is_diagnose_info_enabled()) {
} else if (nullptr == tenant_info || nullptr == inst) {
ret = OB_INVALID_ARGUMENT;
SERVER_LOG(WARN, "Invalid argument", K(ret), KP(inst), KP(tenant_info));
} else if (nullptr == inst->status_.config_) {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "Unexpected null cache inst config", KP(inst->status_.config_));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"user_block_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::BLOCK_CACHE_MISS);
inst->status_.total_hit_cnt_.set( GLOBAL_EVENT_GET(ObStatEventIds::BLOCK_CACHE_HIT));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"user_row_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::ROW_CACHE_MISS);
inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::ROW_CACHE_HIT));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"bf_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::BLOOM_FILTER_CACHE_MISS);
inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::BLOOM_FILTER_CACHE_HIT));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"fuse_row_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::FUSE_ROW_CACHE_MISS);
inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::FUSE_ROW_CACHE_HIT));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"tablet_ls_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::LOCATION_CACHE_MISS);
inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::LOCATION_CACHE_HIT));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"schema_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_CACHE_MISS);
inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_CACHE_HIT));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"opt_table_stat_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::OPT_TABLE_STAT_CACHE_MISS);
inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::OPT_TABLE_STAT_CACHE_HIT));
} else if (0 == strcmp(inst->status_.config_->cache_name_,"opt_column_stat_cache")) {
inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::OPT_COLUMN_STAT_CACHE_MISS);
inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::OPT_COLUMN_STAT_CACHE_HIT));
}
return ret;
}
int ObInfoSchemaKvCacheTable::process_row(const ObKVCacheInst *inst)
{
int ret = OB_SUCCESS;
uint64_t cell_idx = 0;
cur_row_.cells_ = cells_;
cur_row_.count_ = reserved_column_cnt_;
for (int64_t i = 0 ; OB_SUCC(ret) && i < output_column_ids_.count() ; ++i) {
uint64_t col_id = output_column_ids_.at(i);
switch(col_id) {
case TENANT_ID: {
cells_[cell_idx].set_int(inst->tenant_id_);
break;
}
case SVR_IP: {
cells_[cell_idx].set_varchar(ipstr_);
cells_[cell_idx].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
break;
}
case SVR_PORT: {
cells_[cell_idx].set_int(port_);
break;
}
case CACHE_NAME: {
if (NULL != inst->status_.config_) {
cells_[cell_idx].set_varchar(inst->status_.config_->cache_name_);
cells_[cell_idx].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
}
break;
}
case CACHE_ID: {
cells_[cell_idx].set_int(inst->cache_id_);
break;
}
case CACHE_SIZE: {
cells_[cell_idx].set_int(inst->status_.store_size_ + inst->status_.map_size_);
break;
}
case PRIORITY: {
if (NULL != inst->status_.config_) {
cells_[cell_idx].set_int(inst->status_.config_->priority_);
} else {
cells_[cell_idx].set_int(0);
}
break;
}
case CACHE_STORE_SIZE: {
cells_[cell_idx].set_int(inst->status_.store_size_);
break;
}
case CACHE_MAP_SIZE: {
cells_[cell_idx].set_int(inst->status_.map_size_);
break;
}
case KV_CNT: {
cells_[cell_idx].set_int(inst->status_.kv_cnt_);
break;
}
case HIT_RATIO: {
str_buf_.reset();
number::ObNumber num;
double value = inst->status_.get_hit_ratio() * 100;
static const int64_t MAX_DOUBLE_PRINT_SIZE = 64;
char buf[MAX_DOUBLE_PRINT_SIZE];
memset(buf, 0, MAX_DOUBLE_PRINT_SIZE);
if (OB_UNLIKELY(0 > snprintf(buf, MAX_DOUBLE_PRINT_SIZE, "%lf", value))) {
ret = OB_IO_ERROR;
SERVER_LOG(WARN, "Fail to snprintf hit ratio", K(ret), K(errno), KERRNOMSG(errno));
} else if (OB_FAIL(num.from(buf, str_buf_))) {
SERVER_LOG(WARN, "Fail to cast to number", K(ret));
} else {
cells_[cell_idx].set_number(num);
}
break;
}
case TOTAL_PUT_CNT: {
cells_[cell_idx].set_int(inst->status_.total_put_cnt_.value());
break;
}
case TOTAL_HIT_CNT: {
cells_[cell_idx].set_int(inst->status_.total_hit_cnt_.value());
break;
}
case TOTAL_MISS_CNT: {
cells_[cell_idx].set_int(inst->status_.total_miss_cnt_);
break;
}
case HOLD_SIZE: {
cells_[cell_idx].set_int(inst->status_.hold_size_);
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "Invalid column id", K(ret), K(cell_idx), K(output_column_ids_), K(col_id));
break;
}
}
++cell_idx;
}
return ret;
}
}/* ns observer*/
}/* ns oceanbase */

View File

@ -33,13 +33,20 @@ class ObInfoSchemaKvCacheTable : public common::ObVirtualTableScannerIterator
public:
ObInfoSchemaKvCacheTable();
virtual ~ObInfoSchemaKvCacheTable();
virtual int inner_get_next_row(common::ObNewRow *&row);
virtual void reset();
inline void set_addr(common::ObAddr &addr) {addr_ = &addr;}
virtual int set_ip(common::ObAddr *addr);
private:
enum CACHE_COLUMN
virtual int inner_get_next_row(common::ObNewRow *&row);
virtual void reset();
inline void set_addr(common::ObAddr &addr) {addr_ = &addr;}
private:
virtual int set_ip();
virtual int inner_open() override;
int get_tenant_info();
int get_handles(ObKVCacheInst *&inst, ObDiagnoseTenantInfo *& tenant_info);
int set_diagnose_info(ObKVCacheInst *inst, ObDiagnoseTenantInfo *tenant_info);
int process_row(const ObKVCacheInst *inst);
private:
enum CACHE_COLUMN
{
TENANT_ID = common::OB_APP_MIN_COLUMN_ID,
SVR_IP,
@ -62,12 +69,13 @@ private:
int32_t port_;
common::ObSEArray<common::ObKVCacheInstHandle, 100 > inst_handles_;
int16_t cache_iter_;
common::ObStringBuf str_buf_;
common::ObObj cells_[common::OB_ROW_MAX_COLUMNS_COUNT];
common::ObArenaAllocator arenallocator_;
common::ObArray<std::pair<uint64_t, common::ObDiagnoseTenantInfo*> > tenant_dis_;
DISALLOW_COPY_AND_ASSIGN(ObInfoSchemaKvCacheTable);
};
common::ObStringBuf str_buf_;
common::ObObj cells_[common::OB_ROW_MAX_COLUMNS_COUNT];
common::ObArenaAllocator arenallocator_;
common::ObDiagnoseTenantInfo tenant_di_info_;
common::ObArray<std::pair<uint64_t, common::ObDiagnoseTenantInfo*> > tenant_dis_;
DISALLOW_COPY_AND_ASSIGN(ObInfoSchemaKvCacheTable);
};
}
}

View File

@ -184,6 +184,7 @@
#include "observer/virtual_table/ob_all_virtual_ls_archive_stat.h"
#include "observer/virtual_table/ob_all_virtual_dml_stats.h"
#include "observer/virtual_table/ob_tenant_virtual_privilege.h"
#include "observer/virtual_table/ob_all_virtual_kvcache_store_memblock.h"
#include "observer/virtual_table/ob_information_query_response_time.h"
#include "observer/virtual_table/ob_all_virtual_kvcache_handle_leak_info.h"
#include "observer/virtual_table/ob_all_virtual_schema_memory.h"
@ -2220,6 +2221,16 @@ int ObVTIterCreator::create_vt_iter(ObVTableScanParam &params,
}
break;
}
case OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_TID: {
ObAllVirtualKVCacheStoreMemblock *kvcache_store_memblock = nullptr;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObAllVirtualKVCacheStoreMemblock, kvcache_store_memblock))) {
SERVER_LOG(ERROR, "Fail to create __all_virtual_kvcache_store_memblock", K(ret));
} else {
kvcache_store_memblock->set_addr(addr_);
vt_iter = static_cast<ObVirtualTableIterator *>(kvcache_store_memblock);
}
break;
}
case OB_ALL_VIRTUAL_DTL_INTERM_RESULT_MONITOR_TID: {
ObAllDtlIntermResultMonitor *dtl_interm_result_monitor = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObAllDtlIntermResultMonitor, dtl_interm_result_monitor))) {

View File

@ -61,6 +61,7 @@ ob_set_subtarget(ob_share cache
cache/ob_working_set_mgr.cpp
cache/ob_kvcache_hazard_version.cpp
cache/ob_kvcache_handle_ref_checker.cpp
cache/ob_kvcache_pre_warmer.cpp
)
ob_set_subtarget(ob_share scheduler

View File

@ -887,22 +887,6 @@ int ObKVGlobalCache::set_checker_cache_name(const char *cache_name)
return ret;
}
int ObKVGlobalCache::get_tenant_cache_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles)
{
int ret = OB_SUCCESS;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The ObKVGlobalCache has not been inited, ", K(ret));
} else if (0 == tenant_id) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "Invalid argument, ", K(tenant_id), K(ret));
} else if (OB_FAIL(insts_.get_tenant_cache_info(tenant_id, inst_handles))) {
COMMON_LOG(WARN, "Fail to get all cache info, ", K(ret));
}
return ret;
}
void ObKVGlobalCache::print_all_cache_info()
{
if (OB_UNLIKELY(!inited_)) {
@ -913,18 +897,39 @@ void ObKVGlobalCache::print_all_cache_info()
}
}
int ObKVGlobalCache::get_all_cache_info(ObIArray<ObKVCacheInstHandle> &inst_handles)
int ObKVGlobalCache::get_cache_inst_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The ObKVGlobalCache has not been inited", K(ret));
} else if (OB_INVALID_TENANT_ID == tenant_id) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "Invalid argument", K(ret), K(tenant_id));
} else if (OB_FAIL(insts_.get_cache_info(tenant_id, inst_handles))) {
COMMON_LOG(WARN, "Fail to get all cache info", K(ret));
}
return ret;
}
int ObKVGlobalCache::get_memblock_info(const uint64_t tenant_id, ObIArray<ObKVCacheStoreMemblockInfo> &memblock_infos)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The ObKVGlobalCache has not been inited, ", K(ret));
} else if (OB_FAIL(insts_.get_all_cache_info(inst_handles))) {
COMMON_LOG(WARN, "Fail to get all cache info, ", K(ret));
COMMON_LOG(WARN, "The ObKVGlobalCache has not been inited", K(ret));
} else if (0 == tenant_id) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "Invalid argument", K(ret), K(tenant_id));
} else if (OB_FAIL(store_.get_memblock_info(tenant_id, memblock_infos))) {
COMMON_LOG(WARN, "Fail to get all memblock info", K(ret));
}
return ret;
}
int ObKVGlobalCache::get_cache_id(const char *cache_name, int64_t &cache_id)
{
int ret = OB_SUCCESS;

View File

@ -140,8 +140,8 @@ public:
void reload_priority();
int reload_wash_interval();
int64_t get_suitable_bucket_num();
int get_tenant_cache_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles);
int get_all_cache_info(ObIArray<ObKVCacheInstHandle> &inst_handles);
int get_cache_inst_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles);
int get_memblock_info(const uint64_t tenant_id, ObIArray<ObKVCacheStoreMemblockInfo> &memblock_infos);
void print_all_cache_info();
int erase_cache();
virtual int erase_cache(const uint64_t tenant_id) override;

View File

@ -116,6 +116,11 @@ void ObKVCacheInstHandle::reset()
inst_ = NULL;
}
bool ObKVCacheInstHandle::is_valid() const
{
return (nullptr != map_) && (nullptr != inst_);
}
ObKVCacheInstHandle::ObKVCacheInstHandle(const ObKVCacheInstHandle &other)
{
map_ = other.map_;
@ -425,7 +430,7 @@ int ObKVCacheInstMap::set_priority(const int64_t cache_id, const int64_t old_pri
return ret;
}
int ObKVCacheInstMap::get_tenant_cache_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles)
int ObKVCacheInstMap::get_cache_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
@ -437,15 +442,9 @@ int ObKVCacheInstMap::get_tenant_cache_info(const uint64_t tenant_id, ObIArray<O
} else {
DRWLock::RDLockGuard rd_guard(lock_);
for (KVCacheInstMap::iterator iter = inst_map_.begin(); OB_SUCC(ret) && iter != inst_map_.end(); ++iter) {
if (iter->first.tenant_id_ == tenant_id) {
ObKVCacheInstHandle handle;
handle.inst_ = iter->second;
handle.map_ = this;
handle.inst_->status_.map_size_ = iter->second->node_allocator_.allocated();
add_inst_ref(handle.inst_);
if (OB_FAIL(inst_handles.push_back(handle))) {
COMMON_LOG(WARN, "Fail to push info to array, ", K(ret));
}
if (iter->first.tenant_id_ != tenant_id && OB_SYS_TENANT_ID != tenant_id) {
} else if (OB_FAIL(inner_push_inst_handle(iter, inst_handles))) {
COMMON_LOG(WARN, "Fail to inner push cache inst", K(ret));
}
}
}
@ -521,29 +520,6 @@ void ObKVCacheInstMap::print_all_cache_info()
}
}
int ObKVCacheInstMap::get_all_cache_info(ObIArray<ObKVCacheInstHandle> &inst_handles)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The ObKVCacheInstMap has not been inited, ", K(ret));
} else {
DRWLock::RDLockGuard rd_guard(lock_);
for (KVCacheInstMap::iterator iter = inst_map_.begin();
OB_SUCC(ret) && iter != inst_map_.end(); ++iter) {
ObKVCacheInstHandle handle;
handle.inst_ = iter->second;
handle.map_ = this;
handle.inst_->status_.map_size_ = iter->second->node_allocator_.allocated();
add_inst_ref(handle.inst_);
if (OB_FAIL(inst_handles.push_back(handle))) {
COMMON_LOG(WARN, "Fail to push info to array, ", K(ret));
}
}
}
return ret;
}
int ObKVCacheInstMap::set_hold_size(const uint64_t tenant_id, const char *cache_name,
const int64_t hold_size)
{
@ -718,6 +694,22 @@ void ObKVCacheInstMap::de_inst_ref(ObKVCacheInst *inst)
}
}
int ObKVCacheInstMap::inner_push_inst_handle(const KVCacheInstMap::iterator &iter, ObIArray<ObKVCacheInstHandle> &inst_handles)
{
INIT_SUCC(ret);
ObKVCacheInstHandle handle;
handle.inst_ = iter->second;
handle.map_ = this;
handle.inst_->status_.map_size_ = iter->second->node_allocator_.allocated();
add_inst_ref(handle.inst_);
if (OB_FAIL(inst_handles.push_back(handle))) {
COMMON_LOG(WARN, "Fail to push back inst handle to array", K(ret));
}
return ret;
}
}//end namespace common
}//end namespace oceanbase

View File

@ -122,6 +122,7 @@ public:
ObKVCacheInstHandle();
virtual ~ObKVCacheInstHandle();
void reset();
bool is_valid() const;
inline ObKVCacheInst *get_inst() { return inst_; }
ObKVCacheInstHandle(const ObKVCacheInstHandle &other);
ObKVCacheInstHandle& operator = (const ObKVCacheInstHandle& other);
@ -146,8 +147,7 @@ public:
int clean_garbage_inst();
int refresh_score();
int set_priority(const int64_t cache_id, const int64_t old_priority, const int64_t new_priority);
int get_tenant_cache_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles);
int get_all_cache_info(ObIArray<ObKVCacheInstHandle> &inst_handles);
int get_cache_info(const uint64_t tenant_id, ObIArray<ObKVCacheInstHandle> &inst_handles);
void print_all_cache_info();
void print_tenant_cache_info(const uint64_t tenant_id);
@ -162,6 +162,8 @@ private:
typedef ObFixedHashMap<uint64_t, ObTenantMBList *> TenantMBListMap;
void add_inst_ref(ObKVCacheInst *inst);
void de_inst_ref(ObKVCacheInst *inst);
int inner_push_inst_handle(const KVCacheInstMap::iterator &iter, ObIArray<ObKVCacheInstHandle> &inst_handles);
private:
DRWLock lock_;
KVCacheInstMap inst_map_;
ObFixedQueue<ObKVCacheInst> inst_pool_;

View File

@ -0,0 +1,202 @@
// Copyright 2022 Alibaba Inc. All Rights Reserved.
// Author:
// lvling <zhaoruizhe.zrz@alibaba-inc.com>
#include "ob_kvcache_pre_warmer.h"
namespace oceanbase
{
namespace common
{
/*
* -------------------------------------------- ObDataBlockCachePreWarmer --------------------------------------------
*/
ObDataBlockCachePreWarmer::ObDataBlockCachePreWarmer()
: base_percentage_(0),
cache_(nullptr),
read_info_(nullptr),
rest_size_(0),
warm_size_percentage_(100),
update_step_(0),
kvpair_(nullptr),
inst_handle_(),
cache_handle_()
{
}
ObDataBlockCachePreWarmer::~ObDataBlockCachePreWarmer()
{
reset();
}
void ObDataBlockCachePreWarmer::reset()
{
cache_ = nullptr;
read_info_ = nullptr;
base_percentage_ = 0;
rest_size_ = 0;
warm_size_percentage_ = 100;
update_step_ = 0;
reuse();
}
void ObDataBlockCachePreWarmer::reuse()
{
kvpair_ = nullptr;
inst_handle_.reset();
cache_handle_.reset();
}
void ObDataBlockCachePreWarmer::init(const ObTableReadInfo &read_info)
{
int ret = OB_SUCCESS;
if (OB_FAIL(inner_init(DATA_BLOCK_CACHE_PERCENTAGE, read_info, OB_STORE_CACHE.get_block_cache()))) {
COMMON_LOG(WARN, "Fail to inner init data block cache pre warmer", K(ret));
}
}
int ObDataBlockCachePreWarmer::reserve_kvpair(const blocksstable::ObMicroBlockDesc &micro_block_desc,
const int64_t level)
{
int ret = OB_SUCCESS;
int64_t kvpair_size = 0;
if (OB_UNLIKELY(nullptr == cache_ || nullptr == read_info_)) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The block cache pre warmer is not inited", K(ret), KP(cache_), KP(read_info_));
} else if (OB_UNLIKELY(!micro_block_desc.is_valid() || level < 0)) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "Invalid argument", K(ret), K(micro_block_desc), K(level));
} else {
if (level < TOP_LEVEL && (rest_size_ <= 0 || !warm_block(level))) {
ret = OB_BUF_NOT_ENOUGH;
} else if (FALSE_IT(reuse())) {
} else if (OB_FAIL(cache_->reserve_kvpair(micro_block_desc, *read_info_, inst_handle_,
cache_handle_, kvpair_, kvpair_size))) {
COMMON_LOG(WARN, "Fail to reserve block cache value", K(ret), K(micro_block_desc), KPC(read_info_));
} else {
rest_size_ = MAX(0, rest_size_ - kvpair_size);
}
update_rest();
}
COMMON_LOG(DEBUG, "pre warmer reserve cache value details", K(ret), K(kvpair_size), K(level),
K(micro_block_desc));
return ret;
}
int ObDataBlockCachePreWarmer::update_and_put_kvpair(const blocksstable::ObMicroBlockDesc &micro_block_desc)
{
int ret = OB_SUCCESS;
blocksstable::ObIMicroBlockCache::BaseBlockCache *kvcache = nullptr;
if (OB_ISNULL(cache_)) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The block cache pre warmer is not inited", K(ret), KP(cache_));
} else if (OB_UNLIKELY(!micro_block_desc.is_valid() || !inst_handle_.is_valid()
|| !cache_handle_.is_valid() || nullptr == kvpair_)) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "Invalid argument", K(ret), K(micro_block_desc), K(inst_handle_), K(cache_handle_), K(kvpair_));
} else if (cache_->get_cache(kvcache)) {
COMMON_LOG(WARN, "Fail to get block kvcache", K(ret));
} else if (FALSE_IT(static_cast<blocksstable::ObMicroBlockCacheKey *>(kvpair_->key_)->set(
MTL_ID(),
micro_block_desc.macro_id_,
micro_block_desc.block_offset_,
micro_block_desc.buf_size_ + micro_block_desc.header_->header_size_))) {
} else if (OB_FAIL(kvcache->put_kvpair(inst_handle_, kvpair_, cache_handle_))) {
COMMON_LOG(WARN, "Fail to put kvpair into kvcache", K(ret));
}
COMMON_LOG(DEBUG, "pre warmer build cache key and put details", K(ret), K(MTL_ID()), K(rest_size_), K(update_step_),
K(micro_block_desc), KPC(micro_block_desc.header_));
// reuse handles outside
return ret;
}
int ObDataBlockCachePreWarmer::inner_init(const int64_t percentage,
const ObTableReadInfo &read_info,
blocksstable::ObIMicroBlockCache &block_cache)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(percentage < 0 || !read_info.is_valid())) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "Invalid argument", K(ret), K(percentage), K(read_info));
} else {
cache_ = &block_cache;
read_info_ = &read_info;
warm_size_percentage_ = percentage;
inner_update_rest();
}
return ret;
}
void ObDataBlockCachePreWarmer::update_rest()
{
if (OB_UNLIKELY(update_step_++ >= UPDATE_INTERVAL)) {
inner_update_rest();
}
}
void ObDataBlockCachePreWarmer::inner_update_rest()
{
int64_t free_memory = lib::get_tenant_memory_limit(MTL_ID()) - lib::get_tenant_memory_hold(MTL_ID());
rest_size_ = free_memory / 100 * warm_size_percentage_;
calculate_base_percentage(free_memory);
update_step_ = 0;
COMMON_LOG(DEBUG, "pre warmer update rest", K(rest_size_), K(base_percentage_), K(free_memory));
}
void ObDataBlockCachePreWarmer::calculate_base_percentage(const int64_t free_memory)
{
base_percentage_ = MIN(free_memory * 200 / lib::get_tenant_memory_limit(MTL_ID()), 50);
}
bool ObDataBlockCachePreWarmer::warm_block(const int64_t level)
{
bool bret = true;
int64_t threshold = MIN(base_percentage_ + 5 * level, 100);
int64_t random_value = ObTimeUtility::fast_current_time() % 100;
if (100 > threshold) {
bret = random_value <= threshold;
}
COMMON_LOG(DEBUG, "block cache pre warmer filter", K(bret), K(base_percentage_), K(level), K(update_step_),
K(random_value), K(threshold));
return bret;
}
/*
* -------------------------------------------- ObIndexBlockCachePreWarmer --------------------------------------------
*/
ObIndexBlockCachePreWarmer::ObIndexBlockCachePreWarmer()
: ObDataBlockCachePreWarmer()
{
}
ObIndexBlockCachePreWarmer::~ObIndexBlockCachePreWarmer()
{
}
void ObIndexBlockCachePreWarmer::init(const ObTableReadInfo &read_info)
{
int ret = OB_SUCCESS;
if (OB_FAIL(inner_init(INDEX_BLOCK_CACHE_PERCENTAGE, read_info, OB_STORE_CACHE.get_index_block_cache()))) {
COMMON_LOG(WARN, "Fail to inner init index block cache pre warmer", K(ret));
}
}
void ObIndexBlockCachePreWarmer::calculate_base_percentage(const int64_t free_memory)
{
ObDataBlockCachePreWarmer::calculate_base_percentage(free_memory);
base_percentage_ += INDEX_BLOCK_BASE_PERCENTAGE;
}
}; // common
}; // oceanbase

69
src/share/cache/ob_kvcache_pre_warmer.h vendored Normal file
View File

@ -0,0 +1,69 @@
// Copyright 2022 Alibaba Inc. All Rights Reserved.
// Author:
// lvling <zhaoruizhe.zrz@alibaba-inc.com>
#ifndef OCEANBASE_COMMON_KVCACHE_PRE_WARMER_H_
#define OCEANBASE_COMMON_KVCACHE_PRE_WARMER_H_
#include "storage/blocksstable/ob_micro_block_cache.h"
#include "storage/blocksstable/ob_storage_cache_suite.h"
namespace oceanbase
{
namespace common
{
class ObDataBlockCachePreWarmer
{
public:
ObDataBlockCachePreWarmer();
virtual ~ObDataBlockCachePreWarmer();
void reset();
void reuse();
void init(const ObTableReadInfo &read_info);
OB_INLINE bool is_valid() const { return nullptr != cache_; }
int reserve_kvpair(const blocksstable::ObMicroBlockDesc &micro_block_desc, const int64_t level = 0);
int update_and_put_kvpair(const blocksstable::ObMicroBlockDesc &micro_block_desc);
protected:
int inner_init(const int64_t ratio, const ObTableReadInfo &read_info, blocksstable::ObIMicroBlockCache &block_cache);
void update_rest();
void inner_update_rest();
virtual void calculate_base_percentage(const int64_t free_memory);
private:
bool warm_block(const int64_t level);
protected:
int64_t base_percentage_;
private:
static const int64_t DATA_BLOCK_CACHE_PERCENTAGE = 5;
static const int64_t UPDATE_INTERVAL = 50;
static const int64_t TOP_LEVEL = 6;
blocksstable::ObIMicroBlockCache *cache_;
const ObTableReadInfo *read_info_;
int64_t rest_size_;
int64_t warm_size_percentage_;
int64_t update_step_;
ObKVCachePair *kvpair_;
ObKVCacheInstHandle inst_handle_;
ObKVCacheHandle cache_handle_;
};
class ObIndexBlockCachePreWarmer : public ObDataBlockCachePreWarmer
{
public:
ObIndexBlockCachePreWarmer();
virtual ~ObIndexBlockCachePreWarmer();
void init(const ObTableReadInfo &read_info);
protected:
virtual void calculate_base_percentage(const int64_t free_memory) override;
private:
static const int64_t INDEX_BLOCK_CACHE_PERCENTAGE = 2;
static const int64_t INDEX_BLOCK_BASE_PERCENTAGE = 30;
};
}; // common
}; // oceanbase
#endif // OCEANBASE_COMMON_KVCACHE_PRE_WARMER_H_

View File

@ -184,7 +184,7 @@ bool ObKVCacheStore::add_handle_ref(ObKVMemBlockHandle *mb_handle)
return bret;
}
int64_t ObKVCacheStore::get_handle_ref_cnt(ObKVMemBlockHandle *mb_handle)
int64_t ObKVCacheStore::get_handle_ref_cnt(const ObKVMemBlockHandle *mb_handle)
{
if (NULL != mb_handle) {
return mb_handle->handle_ref_.get_ref_cnt();
@ -576,6 +576,9 @@ int ObKVCacheStore::try_flush_washable_mb(
can_try_wash = true;
}
}
} else {
COMMON_LOG(DEBUG, "Cannot flush memblock", K(tenant_id), K(cache_id), K(get_handle_ref_cnt(handle)),
KP(handle), KPC(handle));
}
de_handle_ref(handle);
}
@ -613,6 +616,10 @@ int ObKVCacheStore::try_flush_washable_mb(
}
} // qclock guard
INIT_SUCC(tmp_ret);
if (OB_TMP_FAIL(print_tenant_memblock_info(head))) {
COMMON_LOG(WARN, "Fail to print tenant memblock info", K(tmp_ret));
}
if (size_need_washed == INT64_MAX) {
// flush
ObICacheWasher::ObCacheMemBlock *wash_block = wash_blocks;
@ -647,9 +654,110 @@ int ObKVCacheStore::try_flush_washable_mb(
COMMON_LOG(INFO, "ObKVCache try flush washable memblock details", K(ret), K(tenant_id), K(cache_id), K(size_washed), K(size_need_washed));
retire_mb_handles(retire_list);
COMMON_LOG(DEBUG, "Try flush cache result", K(size_washed), K(size_need_washed), K(tenant_id), K(cache_id), K(ret));
}
return ret;
}
int ObKVCacheStore::inner_push_memblock_info(const ObKVMemBlockHandle &handle, ObIArray<ObKVCacheStoreMemblockInfo> &memblock_infos)
{
INIT_SUCC(ret);
ObKVCacheStoreMemblockInfo mb_info;
STRNCPY(mb_info.cache_name_, handle.inst_->status_.config_->cache_name_, MAX_CACHE_NAME_LENGTH - 1);
mb_info.tenant_id_ = handle.inst_->tenant_id_;
mb_info.cache_id_ = handle.inst_->cache_id_;
mb_info.ref_count_ = get_handle_ref_cnt(&handle);
mb_info.using_status_ = handle.status_;
mb_info.policy_ = handle.policy_;
mb_info.kv_cnt_ = handle.kv_cnt_;
mb_info.get_cnt_ = handle.get_cnt_;
mb_info.recent_get_cnt_ = handle.recent_get_cnt_;
mb_info.priority_ = handle.inst_->status_.config_->priority_;
mb_info.score_ = handle.score_;
mb_info.align_size_ = handle.mem_block_->get_align_size();
if (OB_UNLIKELY(0 > snprintf(mb_info.memblock_ptr_, 32, "%p", handle.mem_block_))) {
ret = OB_IO_ERROR;
COMMON_LOG(WARN, "Fail to snprintf memblock pointer", K(ret), K(errno), KERRNOMSG(errno));
} else if (OB_FAIL(memblock_infos.push_back(mb_info))) {
COMMON_LOG(WARN, "Fail to push memblock info", K(ret), K(mb_info));
}
return ret;
}
int ObKVCacheStore::get_memblock_info(const uint64_t tenant_id, ObIArray<ObKVCacheStoreMemblockInfo> &memblock_infos)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The ObKVCacheStore is not inited", K(ret));
} else {
for (int i = 0 ; OB_SUCC(ret) && i < cur_mb_num_ ; ++i) {
ObKVMemBlockHandle &handle = mb_handles_[i];
if (add_handle_ref(&handle)) {
if (tenant_id != handle.inst_->tenant_id_ && OB_SYS_TENANT_ID != tenant_id) {
} else if (OB_FAIL(inner_push_memblock_info(handle, memblock_infos))) {
COMMON_LOG(WARN, "Fail to inner push memblock info", K(ret));
}
de_handle_ref(&handle);
}
}
}
return ret;
}
int ObKVCacheStore::print_tenant_memblock_info(ObDLink* head)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "The ObKVCacheStore is not inited", K(ret));
} else if (nullptr == head) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "Unexpected nullptr", K(ret), KP(head));
} else {
ContextParam param;
param.set_mem_attr(common::OB_SERVER_TENANT_ID, ObModIds::OB_TEMP_VARIABLES);
CREATE_WITH_TEMP_CONTEXT(param) {
static const int64_t BUFLEN = 1 << 18;
char *buf = (char *)ctxalp(BUFLEN);
if (nullptr == buf) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(WARN, "Fail to allocate memory for print tenant memblock info", K(ret), KP(buf));
} else {
int64_t ctx_pos = 0;
QClockGuard guard(get_qclock());
ObKVMemBlockHandle *handle = static_cast<ObKVMemBlockHandle *>(link_next(head));
while (OB_SUCC(ret) && head != handle) {
if (add_handle_ref(handle)) {
if (OB_FAIL(databuff_printf(buf, BUFLEN, ctx_pos,
"[CACHE] tenant_id=%8ld | cache_id=%8ld | ref_count=%8ld | status=%8d | policy=%8d | kv_cnt=%8ld | get_cnt=%8ld | score=%8lf |\n",
handle->inst_->tenant_id_,
handle->inst_->cache_id_,
get_handle_ref_cnt(handle),
handle->status_,
handle->policy_,
handle->kv_cnt_,
handle->get_cnt_,
handle->score_))) {
COMMON_LOG(WARN, "Fail to print tenant memblock info", K(ret), K(ctx_pos));
}
de_handle_ref(handle);
}
handle = static_cast<ObKVMemBlockHandle *>(link_next(handle));
}
if (OB_SUCC(ret)) {
_OB_LOG(WARN, "[CACHE] len: %8ld tenant sync wash failed, cache memblock info: \n%s", ctx_pos, buf);
}
}
}
}
return ret;
}
@ -859,7 +967,7 @@ bool ObKVCacheStore::compute_tenant_wash_size()
if (OB_FAIL(mem_limit_getter_->get_all_tenant_id(tenant_ids_))) {
COMMON_LOG(WARN, "Fail to get all tenant ids, ", K(ret));
} else if (OB_FAIL(insts_->get_all_cache_info(inst_handles_))) {
} else if (OB_FAIL(insts_->get_cache_info(OB_SYS_TENANT_ID, inst_handles_))) {
COMMON_LOG(WARN, "Fail to get all cache infos, ", K(ret));
}

View File

@ -74,13 +74,13 @@ public:
bool wash();
int get_avg_cache_item_size(const uint64_t tenant_id, const int64_t cache_id,
int64_t &avg_cache_item_size);
int get_washable_size(const uint64_t tenant_id, int64_t &washable_size, const int64_t ratio = 0);
void flush_washable_mbs();
void flush_washable_mbs(const uint64_t tenant_id);
void flush_washable_mbs(const int64_t cache_id);
void flush_washable_mbs(const uint64_t tenant_id, const int64_t cache_id);
int sync_wash_mbs(const uint64_t tenant_id, const int64_t wash_size,
const bool wash_single_mb,
lib::ObICacheWasher::ObCacheMemBlock *&wash_blocks);
@ -95,7 +95,7 @@ public:
virtual bool add_handle_ref(ObKVMemBlockHandle *mb_handle, const uint32_t seq_num);
virtual bool add_handle_ref(ObKVMemBlockHandle *mb_handle);
virtual void de_handle_ref(ObKVMemBlockHandle *mb_handle);
int64_t get_handle_ref_cnt(ObKVMemBlockHandle *mb_handle);
int64_t get_handle_ref_cnt(const ObKVMemBlockHandle *mb_handle);
virtual int64_t get_block_size() const { return block_size_; }
// implement functions of ObIMBWrapperMgr
virtual int alloc(ObKVCacheInst &inst, const enum ObKVCachePolicy policy,
@ -104,14 +104,17 @@ public:
virtual ObKVMemBlockHandle *&get_curr_mb(ObKVCacheInst &inst, const enum ObKVCachePolicy policy);
virtual bool mb_status_match(ObKVCacheInst &inst,
const enum ObKVCachePolicy policy, ObKVMemBlockHandle *mb_handle);
int get_memblock_info(const uint64_t tenant_id, ObIArray<ObKVCacheStoreMemblockInfo> &memblock_infos);
int print_tenant_memblock_info(ObDLink *link);
static const int64_t MAX_RATIO = 6;
private:
int try_flush_washable_mb(
const uint64_t tenant_id,
lib::ObICacheWasher::ObCacheMemBlock *&wash_blocks,
const int64_t cache_id = -1,
const int64_t size_need_washed = INT64_MAX);
int inner_push_memblock_info(const ObKVMemBlockHandle &handle, ObIArray<ObKVCacheStoreMemblockInfo> &memblock_infos);
private:
static const int64_t SYNC_WASH_MB_TIMEOUT_US = 100 * 1000; // 100ms

View File

@ -329,6 +329,17 @@ void ObKVMemBlockHandle::set_full(const double base_mb_score)
score_ += base_mb_score;
ATOMIC_STORE((uint32_t*)(&status_), FULL);
}
/*
* -------------------------------------------------ObKVCacheStoreMemblockInfo------------------------------------------------
*/
bool ObKVCacheStoreMemblockInfo::is_valid() const
{
return tenant_id_ != OB_INVALID_TENANT_ID && cache_id_ >= 0;
}
}//end namespace common
}//end namespace oceanbase

View File

@ -213,6 +213,47 @@ struct ObKVCacheInfo
TO_STRING_KV(K_(inst_key), K_(status));
};
struct ObKVCacheStoreMemblockInfo
{
public:
ObKVCacheStoreMemblockInfo()
: tenant_id_(OB_INVALID_TENANT_ID),
cache_id_(-1),
ref_count_(-1),
using_status_(-1),
policy_(-1),
kv_cnt_(-1),
get_cnt_(-1),
recent_get_cnt_(-1),
priority_(0),
score_(0),
align_size_(-1),
cache_name_(),
memblock_ptr_()
{
memset(cache_name_, 0, MAX_CACHE_NAME_LENGTH);
memset(memblock_ptr_, 0, 32);
}
~ObKVCacheStoreMemblockInfo() = default;
bool is_valid() const;
TO_STRING_KV(K_(tenant_id), K_(cache_id), K_(ref_count), K_(using_status), K_(policy), K_(kv_cnt), K_(get_cnt),
K_(recent_get_cnt), K_(priority), K_(score), K_(align_size), KP_(cache_name), KP_(memblock_ptr));
public:
uint64_t tenant_id_;
int64_t cache_id_;
int64_t ref_count_;
int64_t using_status_;
int64_t policy_;
int64_t kv_cnt_;
int64_t get_cnt_;
int64_t recent_get_cnt_;
int64_t priority_;
double score_;
int64_t align_size_;
char cache_name_[MAX_CACHE_NAME_LENGTH];
char memblock_ptr_[32]; // store memblock address by char[]
};
class ObIMBHandleAllocator
{
public:

View File

@ -5019,6 +5019,285 @@ int ObInnerTableSchema::all_virtual_storage_meta_memory_status_schema(ObTableSch
return ret;
}
int ObInnerTableSchema::all_virtual_kvcache_store_memblock_schema(ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;
uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1;
//generated fields:
table_schema.set_tenant_id(OB_SYS_TENANT_ID);
table_schema.set_tablegroup_id(OB_INVALID_ID);
table_schema.set_database_id(OB_SYS_DATABASE_ID);
table_schema.set_table_id(OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_TID);
table_schema.set_rowkey_split_pos(0);
table_schema.set_is_use_bloomfilter(false);
table_schema.set_progressive_merge_num(0);
table_schema.set_rowkey_column_num(0);
table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK);
table_schema.set_table_type(VIRTUAL_TABLE);
table_schema.set_index_type(INDEX_TYPE_IS_NOT);
table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL);
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_table_name(OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_TNAME))) {
LOG_ERROR("fail to set table_name", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) {
LOG_ERROR("fail to set compress_func_name", K(ret));
}
}
table_schema.set_part_level(PARTITION_LEVEL_ZERO);
table_schema.set_charset_type(ObCharset::get_default_charset());
table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("svr_ip", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
1, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
MAX_IP_ADDR_LENGTH, //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("svr_port", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
2, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("tenant_id", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("cache_id", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("cache_name", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
OB_MAX_KVCACHE_NAME_LENGTH, //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("memblock_ptr", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
32, //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("ref_count", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("status", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("policy", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("kv_cnt", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("get_cnt", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("recent_get_cnt", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("priority", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("score", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
3, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("align_size", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
table_schema.get_part_option().set_part_num(1);
table_schema.set_part_level(PARTITION_LEVEL_ONE);
table_schema.get_part_option().set_part_func_type(PARTITION_FUNC_TYPE_LIST_COLUMNS);
if (OB_FAIL(table_schema.get_part_option().set_part_expr("svr_ip, svr_port"))) {
LOG_WARN("set_part_expr failed", K(ret));
} else if (OB_FAIL(table_schema.mock_list_partition_array())) {
LOG_WARN("mock list partition array failed", K(ret));
}
}
table_schema.set_index_using_type(USING_HASH);
table_schema.set_row_store_type(ENCODING_ROW_STORE);
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
table_schema.set_progressive_merge_round(1);
table_schema.set_storage_format_version(3);
table_schema.set_tablet_id(0);
table_schema.set_max_used_column_id(column_id);
return ret;
}
int ObInnerTableSchema::all_virtual_mock_fk_parent_table_schema(ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;

View File

@ -826,6 +826,7 @@ public:
static int all_virtual_privilege_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_tablet_pointer_status_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_storage_meta_memory_status_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_kvcache_store_memblock_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_mock_fk_parent_table_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_mock_fk_parent_table_history_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_mock_fk_parent_table_column_schema(share::schema::ObTableSchema &table_schema);
@ -2745,6 +2746,7 @@ const schema_create_func virtual_table_schema_creators [] = {
ObInnerTableSchema::all_virtual_privilege_schema,
ObInnerTableSchema::all_virtual_tablet_pointer_status_schema,
ObInnerTableSchema::all_virtual_storage_meta_memory_status_schema,
ObInnerTableSchema::all_virtual_kvcache_store_memblock_schema,
ObInnerTableSchema::all_virtual_mock_fk_parent_table_schema,
ObInnerTableSchema::all_virtual_mock_fk_parent_table_history_schema,
ObInnerTableSchema::all_virtual_mock_fk_parent_table_column_schema,
@ -7105,6 +7107,7 @@ const uint64_t cluster_distributed_vtables [] = {
OB_ALL_VIRTUAL_TABLET_DDL_KV_INFO_TID,
OB_ALL_VIRTUAL_TABLET_POINTER_STATUS_TID,
OB_ALL_VIRTUAL_STORAGE_META_MEMORY_STATUS_TID,
OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_TID,
OB_ALL_VIRTUAL_KVCACHE_HANDLE_LEAK_INFO_TID,
OB_ALL_VIRTUAL_SCHEMA_MEMORY_TID,
OB_ALL_VIRTUAL_SCHEMA_SLOT_TID,

View File

@ -572,6 +572,7 @@ const uint64_t OB_ALL_VIRTUAL_TABLET_DDL_KV_INFO_TID = 12315; // "__all_virtual_
const uint64_t OB_ALL_VIRTUAL_PRIVILEGE_TID = 12316; // "__all_virtual_privilege"
const uint64_t OB_ALL_VIRTUAL_TABLET_POINTER_STATUS_TID = 12317; // "__all_virtual_tablet_pointer_status"
const uint64_t OB_ALL_VIRTUAL_STORAGE_META_MEMORY_STATUS_TID = 12318; // "__all_virtual_storage_meta_memory_status"
const uint64_t OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_TID = 12319; // "__all_virtual_kvcache_store_memblock"
const uint64_t OB_ALL_VIRTUAL_MOCK_FK_PARENT_TABLE_TID = 12320; // "__all_virtual_mock_fk_parent_table"
const uint64_t OB_ALL_VIRTUAL_MOCK_FK_PARENT_TABLE_HISTORY_TID = 12321; // "__all_virtual_mock_fk_parent_table_history"
const uint64_t OB_ALL_VIRTUAL_MOCK_FK_PARENT_TABLE_COLUMN_TID = 12322; // "__all_virtual_mock_fk_parent_table_column"
@ -2475,6 +2476,7 @@ const char *const OB_ALL_VIRTUAL_TABLET_DDL_KV_INFO_TNAME = "__all_virtual_table
const char *const OB_ALL_VIRTUAL_PRIVILEGE_TNAME = "__all_virtual_privilege";
const char *const OB_ALL_VIRTUAL_TABLET_POINTER_STATUS_TNAME = "__all_virtual_tablet_pointer_status";
const char *const OB_ALL_VIRTUAL_STORAGE_META_MEMORY_STATUS_TNAME = "__all_virtual_storage_meta_memory_status";
const char *const OB_ALL_VIRTUAL_KVCACHE_STORE_MEMBLOCK_TNAME = "__all_virtual_kvcache_store_memblock";
const char *const OB_ALL_VIRTUAL_MOCK_FK_PARENT_TABLE_TNAME = "__all_virtual_mock_fk_parent_table";
const char *const OB_ALL_VIRTUAL_MOCK_FK_PARENT_TABLE_HISTORY_TNAME = "__all_virtual_mock_fk_parent_table_history";
const char *const OB_ALL_VIRTUAL_MOCK_FK_PARENT_TABLE_COLUMN_TNAME = "__all_virtual_mock_fk_parent_table_column";

View File

@ -10697,7 +10697,34 @@ def_table_schema(
vtable_route_policy = 'distributed',
)
# 12319: __all_virtual_kvcache_store_memblock
def_table_schema(
owner = 'zhaoruizhe.zrz',
table_name = '__all_virtual_kvcache_store_memblock',
table_id = '12319',
table_type = 'VIRTUAL_TABLE',
gm_columns = [],
rowkey_columns = [
],
normal_columns = [
('svr_ip', 'varchar:MAX_IP_ADDR_LENGTH', 'false'),
('svr_port', 'int'),
('tenant_id', 'int'),
('cache_id', 'int'),
('cache_name', 'varchar:OB_MAX_KVCACHE_NAME_LENGTH'),
('memblock_ptr', 'varchar:32'),
('ref_count', 'int'),
('status', 'int'),
('policy', 'int'),
('kv_cnt', 'int'),
('get_cnt', 'int'),
('recent_get_cnt', 'int'),
('priority', 'int'),
('score', 'number:38:3'),
('align_size', 'int'),
],
vtable_route_policy = 'distributed',
partition_columns = ['svr_ip', 'svr_port'],
)
def_table_schema(**gen_iterate_virtual_table_def(
table_id = '12320',

View File

@ -3426,7 +3426,12 @@ int ObStaticEngineCG::generate_normal_tsc(ObLogTableScan &op, ObTableScanSpec &s
CK(OB_NOT_NULL(schema_guard));
if (OB_SUCC(ret) && NULL != op.get_pre_query_range()) {
OZ(spec.tsc_ctdef_.pre_query_range_.deep_copy(*op.get_pre_query_range()));
op.get_pre_query_range()->is_get(spec.tsc_ctdef_.scan_ctdef_.is_get_);
if (OB_FAIL(ret)) {
} else if (!op.is_skip_scan() && OB_FAIL(spec.tsc_ctdef_.pre_query_range_.reset_skip_scan_range())) {
LOG_WARN("reset skip scan range failed", K(ret));
} else if (OB_FAIL(spec.tsc_ctdef_.pre_query_range_.is_get(spec.tsc_ctdef_.scan_ctdef_.is_get_))) {
LOG_WARN("extract the query range whether get failed", K(ret));
}
}
bool is_equal_and = true;
@ -3462,8 +3467,11 @@ int ObStaticEngineCG::generate_normal_tsc(ObLogTableScan &op, ObTableScanSpec &s
}
root = root->and_next_;
}
spec.tsc_ctdef_.pre_query_range_.set_is_equal_and(is_equal_and);
spec.tsc_ctdef_.pre_query_range_.get_equal_offs().assign(equal_offs);
// TODO @baixian.zr the above optimization is overrided by ObTscCgService::generate_tsc_ctdef before this commit
// but after the deep copy of pre_query_range_ is removed in ObTscCgService::generate_tsc_ctdef,
// error is returned in such sql 'set global x=y', should fix this;
// spec.tsc_ctdef_.pre_query_range_.set_is_equal_and(is_equal_and);
// spec.tsc_ctdef_.pre_query_range_.get_equal_offs().assign(equal_offs);
OZ(ob_write_string(phy_plan_->get_allocator(), op.get_table_name(), tbl_name));
OZ(ob_write_string(phy_plan_->get_allocator(), op.get_index_name(), index_name));

View File

@ -28,30 +28,21 @@ int ObTscCgService::generate_tsc_ctdef(ObLogTableScan &op, ObTableScanCtDef &tsc
{
int ret = OB_SUCCESS;
ObDASScanCtDef &scan_ctdef = tsc_ctdef.scan_ctdef_;
if (op.get_pre_query_range() != nullptr) {
if (OB_FAIL(tsc_ctdef.pre_query_range_.deep_copy(*op.get_pre_query_range()))) {
LOG_WARN("deep copy tsc ctdef pre query range failed", K(ret));
} else if (OB_FAIL(op.get_pre_query_range()->is_get(scan_ctdef.is_get_))) {
LOG_WARN("extract the query range whether get failed", K(ret));
}
ObQueryFlag query_flag;
if (op.is_need_feedback() &&
(op.get_plan()->get_optimizer_context().get_phy_plan_type() == OB_PHY_PLAN_LOCAL ||
op.get_plan()->get_optimizer_context().get_phy_plan_type() == OB_PHY_PLAN_REMOTE)) {
++(cg_.phy_plan_->get_access_table_num());
query_flag.is_need_feedback_ = true;
}
if (OB_SUCC(ret)) {
ObQueryFlag query_flag;
if (op.is_need_feedback() &&
(op.get_plan()->get_optimizer_context().get_phy_plan_type() == OB_PHY_PLAN_LOCAL ||
op.get_plan()->get_optimizer_context().get_phy_plan_type() == OB_PHY_PLAN_REMOTE)) {
++(cg_.phy_plan_->get_access_table_num());
query_flag.is_need_feedback_ = true;
}
ObOrderDirection scan_direction = op.get_scan_direction();
if (is_descending_direction(scan_direction)) {
query_flag.scan_order_ = ObQueryFlag::Reverse;
} else {
query_flag.scan_order_ = ObQueryFlag::Forward;
}
tsc_ctdef.scan_flags_ = query_flag;
ObOrderDirection scan_direction = op.get_scan_direction();
if (is_descending_direction(scan_direction)) {
query_flag.scan_order_ = ObQueryFlag::Reverse;
} else {
query_flag.scan_order_ = ObQueryFlag::Forward;
}
tsc_ctdef.scan_flags_ = query_flag;
if (OB_SUCC(ret) && (OB_NOT_NULL(op.get_flashback_query_expr()))) {
if (OB_FAIL(cg_.generate_rt_expr(*op.get_flashback_query_expr(),
tsc_ctdef.flashback_item_.flashback_query_expr_))) {

View File

@ -592,6 +592,7 @@ int ObDASScanOp::reuse_iter()
LOG_WARN("reuse lookup iterator failed", K(ret));
} else {
scan_param_.key_ranges_.reuse();
scan_param_.ss_key_ranges_.reuse();
scan_param_.mbr_filters_.reuse();
}
return ret;
@ -612,7 +613,8 @@ int ObDASScanOp::set_lookup_tablet_id(const ObTabletID &tablet_id)
OB_SERIALIZE_MEMBER((ObDASScanOp, ObIDASTaskOp),
scan_param_.key_ranges_,
scan_ctdef_,
scan_rtdef_);
scan_rtdef_,
scan_param_.ss_key_ranges_);
ObDASScanResult::ObDASScanResult()
: ObIDASTaskResult(),
@ -1179,6 +1181,7 @@ int ObLocalIndexLookupOp::reset_lookup_state(bool need_switch_param)
if (lookup_iter_ != nullptr) {
scan_param_.need_switch_param_ = need_switch_param;
scan_param_.key_ranges_.reuse();
scan_param_.ss_key_ranges_.reuse();
}
if (OB_SUCC(ret) && lookup_memctx_ != nullptr) {
lookup_memctx_->reset_remain_one_page();

View File

@ -39,10 +39,13 @@ int ObGITaskSet::get_task_at_pos(ObGranuleTaskInfo &info, const int64_t &pos) co
int64_t cur_idx = gi_task_set_.at(pos).idx_;
info.tablet_loc_ = const_cast<ObDASTabletLoc *>(gi_task_set_.at(pos).tablet_loc_);
info.ranges_.reset();
info.ss_ranges_.reset();
for (int64_t i = pos; OB_SUCC(ret) && i < gi_task_set_.count(); i++) {
if (cur_idx == gi_task_set_.at(i).idx_) {
if (OB_FAIL(info.ranges_.push_back(gi_task_set_.at(i).range_))) {
LOG_WARN("push back ranges failed", K(ret));
} else if (OB_FAIL(info.ss_ranges_.push_back(gi_task_set_.at(i).ss_range_))) {
LOG_WARN("push back skip scan ranges failed", K(ret));
}
} else {
break;
@ -89,10 +92,13 @@ int ObGITaskSet::get_next_gi_task(ObGranuleTaskInfo &info)
int64_t cur_idx = gi_task_set_.at(cur_pos_).idx_;
info.tablet_loc_ = gi_task_set_.at(cur_pos_).tablet_loc_;
info.ranges_.reset();
info.ss_ranges_.reset();
for (int64_t i = cur_pos_; OB_SUCC(ret) && i < gi_task_set_.count(); i++) {
if (cur_idx == gi_task_set_.at(i).idx_) {
if (OB_FAIL(info.ranges_.push_back(gi_task_set_.at(i).range_))) {
LOG_WARN("push back ranges failed", K(ret));
} else if (OB_FAIL(info.ss_ranges_.push_back(gi_task_set_.at(i).ss_range_))) {
LOG_WARN("push back skip scan ranges failed", K(ret));
}
if (i == (gi_task_set_.count() - 1)) {
cur_pos_ = gi_task_set_.count();
@ -199,25 +205,30 @@ int ObGITaskSet::set_block_order(bool desc)
int ObGITaskSet::construct_taskset(ObIArray<ObDASTabletLoc*> &taskset_tablets,
ObIArray<ObNewRange> &taskset_ranges,
ObIArray<ObNewRange> &ss_ranges,
ObIArray<int64_t> &taskset_idxs,
ObGIRandomType random_type)
{
int ret = OB_SUCCESS;
if (taskset_tablets.count() != taskset_ranges.count() ||
taskset_tablets.count() != taskset_idxs.count() ||
taskset_tablets.empty()) {
if (OB_UNLIKELY(taskset_tablets.count() != taskset_ranges.count() ||
taskset_tablets.count() != taskset_idxs.count() ||
taskset_tablets.empty() || ss_ranges.count() > 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("taskest count err", K(taskset_tablets.count()),
K(taskset_ranges),
K(taskset_idxs));
K(taskset_idxs),
K(ss_ranges.count()));
} else if (!(GI_RANDOM_NONE <= random_type && random_type <= GI_RANDOM_RANGE)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("random type err", K(random_type));
} else if (gi_task_set_.empty() && OB_FAIL(gi_task_set_.reserve(taskset_tablets.count()))) {
LOG_WARN("failed to prepare allocate", K(ret));
} else {
ObNewRange whole_range;
whole_range.set_whole_range();
ObNewRange &ss_range = ss_ranges.empty() ? whole_range : ss_ranges.at(0);
for (int64_t i = 0; OB_SUCC(ret) && i < taskset_tablets.count(); i++) {
ObGITaskInfo task_info(taskset_tablets.at(i), taskset_ranges.at(i), taskset_idxs.at(i));
ObGITaskInfo task_info(taskset_tablets.at(i), taskset_ranges.at(i), ss_range, taskset_idxs.at(i));
if (random_type != ObGITaskSet::GI_RANDOM_NONE) {
task_info.hash_value_ = common::murmurhash(&task_info.idx_, sizeof(task_info.idx_), 0);
}
@ -673,6 +684,7 @@ int ObGranuleSplitter::split_gi_task(ObGranulePumpArgs &args,
{
int ret = OB_SUCCESS;
ObSEArray<ObNewRange, 16> ranges;
ObSEArray<ObNewRange, 16> ss_ranges;
DASTabletLocSEArray taskset_tablets;
ObSEArray<ObNewRange, 16> taskset_ranges;
ObSEArray<int64_t, 16> taskset_idxs;
@ -686,7 +698,8 @@ int ObGranuleSplitter::split_gi_task(ObGranulePumpArgs &args,
} else if (tablets.count() <= 0 || OB_ISNULL(args.ctx_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("the task has an empty tablets", K(ret), K(tablets));
} else if (OB_FAIL(get_query_range(*args.ctx_, tsc->get_query_range(), ranges, table_id, op_id, partition_granule, args.with_param_down()))) {
} else if (OB_FAIL(get_query_range(*args.ctx_, tsc->get_query_range(), ranges, ss_ranges,
table_id, op_id, partition_granule, args.with_param_down()))) {
LOG_WARN("get query range failed", K(ret));
} else if (ranges.count() <= 0) {
ret = OB_ERR_UNEXPECTED;
@ -703,9 +716,14 @@ int ObGranuleSplitter::split_gi_task(ObGranulePumpArgs &args,
taskset_idxs,
range_independent))) {
LOG_WARN("failed to get graunle task", K(ret), K(ranges), K(tablets));
} else if (OB_FAIL(task_set.construct_taskset(taskset_tablets, taskset_ranges, taskset_idxs, random_type))) {
} else if (OB_FAIL(task_set.construct_taskset(taskset_tablets,
taskset_ranges,
ss_ranges,
taskset_idxs,
random_type))) {
LOG_WARN("construct taskset failed", K(ret), K(taskset_tablets),
K(taskset_ranges),
K(ss_ranges),
K(taskset_idxs),
K(random_type));
}
@ -715,6 +733,7 @@ int ObGranuleSplitter::split_gi_task(ObGranulePumpArgs &args,
int ObGranuleSplitter::get_query_range(ObExecContext &ctx,
const ObQueryRange &tsc_pre_query_range,
ObIArray<ObNewRange> &ranges,
ObIArray<ObNewRange> &ss_ranges,
int64_t table_id,
int64_t op_id,
bool partition_granule,
@ -722,6 +741,7 @@ int ObGranuleSplitter::get_query_range(ObExecContext &ctx,
{
int ret = OB_SUCCESS;
ObQueryRangeArray scan_ranges;
ObQueryRangeArray skip_scan_ranges;
ObGetMethodArray get_method;
ObPhysicalPlanCtx *plan_ctx = nullptr;
bool has_extract_query_range = false;
@ -757,6 +777,12 @@ int ObGranuleSplitter::get_query_range(ObExecContext &ctx,
get_method,
ObBasicSessionInfo::create_dtc_params(ctx.get_my_session())))) {
LOG_WARN("failed to get scan ranges", K(ret));
} else if (OB_FAIL(tsc_pre_query_range.get_ss_tablet_ranges(
ctx.get_allocator(),
ctx,
skip_scan_ranges,
ObBasicSessionInfo::create_dtc_params(ctx.get_my_session())))) {
LOG_WARN("failed to final extract index skip query range", K(ret));
} else {
has_extract_query_range = true;
}
@ -783,12 +809,37 @@ int ObGranuleSplitter::get_query_range(ObExecContext &ctx,
get_method,
ObBasicSessionInfo::create_dtc_params(ctx.get_my_session())))) {
LOG_WARN("failed to get scan ranges", K(ret));
} else if (OB_FAIL(tsc_pre_query_range.get_ss_tablet_ranges(
ctx.get_allocator(),
ctx,
skip_scan_ranges,
ObBasicSessionInfo::create_dtc_params(ctx.get_my_session())))) {
LOG_WARN("failed to final extract index skip query range", K(ret));
} else {
has_extract_query_range = true;
}
}
LOG_DEBUG("gi get the scan range", K(ret), K(partition_granule), K(has_extract_query_range), K(scan_ranges));
LOG_DEBUG("gi get the scan range", K(ret), K(partition_granule), K(has_extract_query_range),
K(scan_ranges), K(skip_scan_ranges));
if (OB_SUCC(ret)) {
// index skip scan, ranges from extract_pre_query_range/get_ss_tablet_ranges,
// prefix range and postfix range is single range
ObNewRange *ss_range = NULL;
ObNewRange whole_range;
whole_range.set_whole_range();
if (!skip_scan_ranges.empty() &&
(OB_ISNULL(skip_scan_ranges.at(0)) ||
OB_UNLIKELY(1 != skip_scan_ranges.count() || 1 != scan_ranges.count()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected index skip scan range", K(ret), K(scan_ranges), K(skip_scan_ranges));
} else if (OB_FAIL(ss_ranges.push_back(skip_scan_ranges.empty()
? whole_range : *skip_scan_ranges.at(0)))) {
LOG_WARN("push back ranges failed", K(ret));
} else {
ss_ranges.at(ss_ranges.count() - 1).table_id_ = table_id;
}
}
for (int64_t i = 0; i < scan_ranges.count() && OB_SUCC(ret); ++i) {
if (OB_ISNULL(scan_ranges.at(i))) {
ret = OB_ERR_UNEXPECTED;
@ -1187,6 +1238,7 @@ int ObPartitionWiseGranuleSplitter::split_insert_gi_task(ObGranulePumpArgs &args
// insert的每一个partition对应的区间默认是[min_rowkey,max_rowkey]
ObNewRange each_partition_range;
ObSEArray<ObNewRange, 4> ranges;
ObSEArray<ObNewRange, 1> empty_ss_ranges;
DASTabletLocSEArray taskset_tablets;
ObSEArray<ObNewRange, 4> taskset_ranges;
ObSEArray<int64_t, 4> taskset_idxs;
@ -1213,7 +1265,8 @@ int ObPartitionWiseGranuleSplitter::split_insert_gi_task(ObGranulePumpArgs &args
taskset_idxs,
range_independent))) {
LOG_WARN("failed to get insert graunle task", K(ret), K(each_partition_range), K(tablets));
} else if (OB_FAIL(task_set.construct_taskset(taskset_tablets, taskset_ranges, taskset_idxs, random_type))) {
} else if (OB_FAIL(task_set.construct_taskset(taskset_tablets, taskset_ranges,
empty_ss_ranges, taskset_idxs, random_type))) {
// INSERT的任务划分一定是 partition wise的,并且INSERT算子每次rescan仅仅需要每一个task对应的partition key,
// `ranges`,`idx`等任务参数是不需要
LOG_WARN("construct taskset failed", K(ret), K(taskset_tablets),

View File

@ -94,15 +94,20 @@ class ObGITaskSet {
public:
struct ObGITaskInfo
{
ObGITaskInfo() : tablet_loc_(nullptr), range_(), idx_(0), hash_value_(0) {}
ObGITaskInfo(ObDASTabletLoc *tablet_loc, common::ObNewRange range, int64_t idx) :
tablet_loc_(tablet_loc), range_(range), idx_(idx), hash_value_(0) {}
ObGITaskInfo() : tablet_loc_(nullptr), range_(), ss_range_(), idx_(0), hash_value_(0) {}
ObGITaskInfo(ObDASTabletLoc *tablet_loc,
common::ObNewRange range,
common::ObNewRange ss_range,
int64_t idx) :
tablet_loc_(tablet_loc), range_(range), ss_range_(ss_range), idx_(idx), hash_value_(0) {}
TO_STRING_KV(KPC(tablet_loc_),
K(range_),
K(ss_range_),
K(idx_),
K(hash_value_));
ObDASTabletLoc *tablet_loc_;
common::ObNewRange range_;
common::ObNewRange ss_range_;
int64_t idx_;
uint64_t hash_value_;
};
@ -124,6 +129,7 @@ public:
int set_block_order(bool asc);
int construct_taskset(common::ObIArray<ObDASTabletLoc*> &taskset_tablets,
common::ObIArray<ObNewRange> &taskset_ranges,
common::ObIArray<ObNewRange> &ss_ranges,
common::ObIArray<int64_t> &taskset_idxs,
ObGIRandomType random_type);
public:
@ -169,6 +175,7 @@ public :
static int get_query_range(ObExecContext &ctx,
const ObQueryRange &tsc_pre_query_range,
ObIArray<ObNewRange> &ranges,
ObIArray<ObNewRange> &ss_ranges,
int64_t table_id,
int64_t op_id,
bool partition_granule,

View File

@ -237,6 +237,7 @@ void ObTableScanOpInput::reset()
{
tablet_loc_ = nullptr;
key_ranges_.reset();
ss_key_ranges_.reset();
mbr_filters_.reset();
range_array_pos_.reset();
not_need_extract_query_range_ = false;
@ -247,7 +248,8 @@ OB_DEF_SERIALIZE_SIZE(ObTableScanOpInput)
int len = 0;
LST_DO_CODE(OB_UNIS_ADD_LEN,
key_ranges_,
not_need_extract_query_range_);
not_need_extract_query_range_,
ss_key_ranges_);
return len;
}
@ -256,7 +258,8 @@ OB_DEF_SERIALIZE(ObTableScanOpInput)
int ret = OB_SUCCESS;
LST_DO_CODE(OB_UNIS_ENCODE,
key_ranges_,
not_need_extract_query_range_);
not_need_extract_query_range_,
ss_key_ranges_);
return ret;
}
@ -274,6 +277,18 @@ OB_DEF_DESERIALIZE(ObTableScanOpInput)
exec_ctx_.get_allocator(), buf, data_len, pos))) {
LOG_WARN("range deserialize failed", K(ret));
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(serialization::decode_vi64(buf, data_len, pos, &cnt))) {
LOG_WARN("decode failed", K(ret));
} else if (OB_FAIL(ss_key_ranges_.prepare_allocate(cnt))) {
LOG_WARN("array prepare allocate failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < cnt; i++) {
if (OB_FAIL(ss_key_ranges_.at(i).deserialize(exec_ctx_.get_allocator(),
buf, data_len, pos))) {
LOG_WARN("range deserialize failed", K(ret));
}
}
}
if (OB_SUCC(ret)) {
LST_DO_CODE(OB_UNIS_DECODE, not_need_extract_query_range_);
@ -761,6 +776,7 @@ int ObTableScanOp::prepare_all_das_tasks()
LOG_WARN("prepare das task failed", K(ret));
} else {
MY_INPUT.key_ranges_.reuse();
MY_INPUT.ss_key_ranges_.reuse();
}
}
}
@ -962,7 +978,7 @@ int ObTableScanOp::prepare_batch_scan_range()
LOG_WARN("prepare single scan range failed", K(ret));
}
}
LOG_DEBUG("after prepare batch scan range", K(MY_INPUT.key_ranges_));
LOG_DEBUG("after prepare batch scan range", K(MY_INPUT.key_ranges_), K(MY_INPUT.ss_key_ranges_));
return ret;
}
@ -996,6 +1012,7 @@ int ObTableScanOp::prepare_single_scan_range(int64_t group_idx)
{
int ret = OB_SUCCESS;
ObQueryRangeArray key_ranges;
ObQueryRangeArray ss_key_ranges;
ObGetMethodArray get_method;
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
ObIAllocator &range_allocator = (table_rescan_allocator_ != nullptr ?
@ -1039,20 +1056,51 @@ int ObTableScanOp::prepare_single_scan_range(int64_t group_idx)
get_method,
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
LOG_WARN("failed to extract pre query ranges", K(ret));
} else if (OB_FAIL(MY_CTDEF.pre_query_range_.get_ss_tablet_ranges(range_allocator,
ctx_,
ss_key_ranges,
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
LOG_WARN("failed to final extract index skip query range", K(ret));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < key_ranges.count(); ++i) {
ObNewRange *key_range = key_ranges.at(i);
key_range->table_id_ = MY_CTDEF.scan_ctdef_.ref_table_id_;
key_range->group_idx_ = group_idx;
if (OB_FAIL(MY_INPUT.key_ranges_.push_back(*key_range))) {
LOG_WARN("store key range in TSC input failed", K(ret));
if (OB_FAIL(ret)) {
} else if (!ss_key_ranges.empty()) {
// index skip scan, ranges from extract_pre_query_range/get_ss_tablet_ranges,
// prefix range and postfix range is single range
if (1 != ss_key_ranges.count() || 1 != key_ranges.count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected index skip scan range", K(ret), K(key_ranges), K(ss_key_ranges));
} else {
key_ranges.at(0)->table_id_ = MY_CTDEF.scan_ctdef_.ref_table_id_;
key_ranges.at(0)->group_idx_ = group_idx;
ss_key_ranges.at(0)->table_id_ = MY_CTDEF.scan_ctdef_.ref_table_id_;
ss_key_ranges.at(0)->group_idx_ = group_idx;
if (OB_FAIL(MY_INPUT.key_ranges_.push_back(*key_ranges.at(0)))
|| OB_FAIL(MY_INPUT.ss_key_ranges_.push_back(*ss_key_ranges.at(0)))) {
LOG_WARN("store key range in TSC input failed", K(ret));
}
}
} else {
ObNewRange whole_range;
ObNewRange *key_range = NULL;
whole_range.set_whole_range();
whole_range.table_id_ = MY_CTDEF.scan_ctdef_.ref_table_id_;
whole_range.group_idx_ = group_idx;
for (int64_t i = 0; OB_SUCC(ret) && i < key_ranges.count(); ++i) {
key_range = key_ranges.at(i);
key_range->table_id_ = MY_CTDEF.scan_ctdef_.ref_table_id_;
key_range->group_idx_ = group_idx;
if (OB_FAIL(MY_INPUT.key_ranges_.push_back(*key_range))
|| OB_FAIL(MY_INPUT.ss_key_ranges_.push_back(whole_range))) {
LOG_WARN("store key range in TSC input failed", K(ret));
}
}
}
if (OB_SUCC(ret) && MY_SPEC.is_vt_mapping_) {
OZ(OB_FAIL(vt_result_converter_->convert_key_ranges(MY_INPUT.key_ranges_)));
}
LOG_TRACE("prepare single scan range", K(ret), K(key_ranges), K(MY_INPUT.key_ranges_));
LOG_TRACE("prepare single scan range", K(ret), K(key_ranges), K(MY_INPUT.key_ranges_),
K(MY_INPUT.ss_key_ranges_));
return ret;
}
@ -1338,6 +1386,7 @@ int ObTableScanOp::inner_rescan()
output_row_cnt_ = 0;
iter_end_ = false;
MY_INPUT.key_ranges_.reuse();
MY_INPUT.ss_key_ranges_.reuse();
MY_INPUT.mbr_filters_.reuse();
if (OB_FAIL(ObOperator::inner_rescan())) {
LOG_WARN("rescan operator failed", K(ret));
@ -1381,6 +1430,7 @@ int ObTableScanOp::close_and_reopen()
tsc_rtdef_.lookup_rtdef_->stmt_allocator_.set_alloc(&das_ref_.get_das_alloc());
}
MY_INPUT.key_ranges_.reuse();
MY_INPUT.ss_key_ranges_.reuse();
MY_INPUT.mbr_filters_.reuse();
}
return ret;
@ -1460,6 +1510,7 @@ int ObTableScanOp::local_iter_reuse()
} else {
tsc_rtdef_.scan_rtdef_.scan_allocator_.set_alloc(table_rescan_allocator_);
MY_INPUT.key_ranges_.reuse();
MY_INPUT.ss_key_ranges_.reuse();
MY_INPUT.mbr_filters_.reuse();
}
return ret;
@ -1833,13 +1884,19 @@ int ObTableScanOp::cherry_pick_range_by_tablet_id(ObDASScanOp *scan_op)
{
int ret = OB_SUCCESS;
ObIArray<ObNewRange> &scan_ranges = scan_op->get_scan_param().key_ranges_;
ObIArray<ObNewRange> &ss_ranges = scan_op->get_scan_param().ss_key_ranges_;
ObIArray<ObSpatialMBR> &mbr_filters = scan_op->get_scan_param().mbr_filters_;
const ObIArray<ObNewRange> &input_ranges = MY_INPUT.key_ranges_;
const ObIArray<ObNewRange> &input_ss_ranges = MY_INPUT.ss_key_ranges_;
const ObIArray<ObSpatialMBR> &input_filters = MY_INPUT.mbr_filters_;
ObDASGroupScanOp *batch_op = DAS_GROUP_SCAN_OP(scan_op);
bool add_all = false;
bool prune_all = true;
if (ObPartitionLevel::PARTITION_LEVEL_MAX == MY_SPEC.part_level_
if (OB_UNLIKELY(input_ranges.count() != input_ss_ranges.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("ranges and skip scan postfix ranges mismatch", K(ret), K(input_ranges.count()),
K(input_ss_ranges.count()));
} else if (ObPartitionLevel::PARTITION_LEVEL_MAX == MY_SPEC.part_level_
|| ObPartitionLevel::PARTITION_LEVEL_ZERO == MY_SPEC.part_level_
|| (input_ranges.count() <= 1)) {
add_all = true;
@ -1857,6 +1914,8 @@ int ObTableScanOp::cherry_pick_range_by_tablet_id(ObDASScanOp *scan_op)
prune_all = false;
if (OB_FAIL(scan_ranges.push_back(input_ranges.at(i)))) {
LOG_WARN("store input range to scan param failed", K(ret));
} else if (OB_FAIL(ss_ranges.push_back(input_ss_ranges.at(i)))) {
LOG_WARN("store input skip scan range to scan param failed", K(ret));
} else if (!input_ranges.at(i).is_physical_rowid_range_) {
//do nothing
} else if (OB_UNLIKELY(MY_SPEC.get_columns_desc().count() < 1)) {
@ -1885,15 +1944,20 @@ int ObTableScanOp::cherry_pick_range_by_tablet_id(ObDASScanOp *scan_op)
}
if (OB_SUCC(ret) && prune_all && !input_ranges.empty()) {
ObNewRange false_range;
ObNewRange whole_range;
false_range.set_false_range();
false_range.group_idx_ = input_ranges.at(0).group_idx_;
whole_range.set_whole_range();
if (OB_FAIL(scan_ranges.push_back(false_range))) {
LOG_WARN("store false range to scan ranges failed", K(ret));
} else if (OB_FAIL(ss_ranges.push_back(whole_range))) {
LOG_WARN("store whole range to skip scan ranges failed", K(ret));
}
}
if (OB_SUCC(ret)) {
LOG_DEBUG("range after pruning", K(input_ranges), K(scan_ranges), K_(group_size),
"tablet_id", scan_op->get_tablet_id());
"tablet_id", scan_op->get_tablet_id(),
K(input_ss_ranges), K(ss_ranges));
}
return ret;
}
@ -2057,9 +2121,11 @@ int ObTableScanOp::reassign_task_ranges(ObGranuleTaskInfo &info)
if (MY_SPEC.gi_above_ && !iter_end_) {
if (OB_UNLIKELY(MY_SPEC.get_query_range().is_contain_geo_filters())) {
MY_INPUT.key_ranges_.reuse();
MY_INPUT.ss_key_ranges_.reuse();
MY_INPUT.mbr_filters_.reuse();
} else if (!MY_INPUT.get_need_extract_query_range()) {
if (OB_FAIL(MY_INPUT.key_ranges_.assign(info.ranges_))) {
if (OB_FAIL(MY_INPUT.key_ranges_.assign(info.ranges_)) ||
OB_FAIL(MY_INPUT.ss_key_ranges_.assign(info.ss_ranges_))) {
LOG_WARN("assign the range info failed", K(ret), K(info));
} else if (MY_SPEC.is_vt_mapping_) {
if (OB_FAIL(vt_result_converter_->convert_key_ranges(MY_INPUT.key_ranges_))) {
@ -2069,6 +2135,7 @@ int ObTableScanOp::reassign_task_ranges(ObGranuleTaskInfo &info)
} else {
// use prepare() to set key ranges if px do not extract query range
MY_INPUT.key_ranges_.reuse();
MY_INPUT.ss_key_ranges_.reuse();
MY_INPUT.mbr_filters_.reuse();
LOG_DEBUG("do prepare!!!");
}

View File

@ -201,6 +201,7 @@ public:
protected:
ObDASTabletLoc *tablet_loc_;
common::ObSEArray<common::ObNewRange, 1> key_ranges_;
common::ObSEArray<common::ObNewRange, 1> ss_key_ranges_;
common::ObSEArray<common::ObSpatialMBR, 1> mbr_filters_;
common::ObPosArray range_array_pos_;
// if the query range was extracted before(include whole range), tsc not need to extract every time

View File

@ -87,13 +87,15 @@ class ObGranuleTaskInfo
public:
ObGranuleTaskInfo()
: ranges_(),
ss_ranges_(),
tablet_loc_(nullptr),
task_id_(0)
{ }
virtual ~ObGranuleTaskInfo() { }
TO_STRING_KV(K_(ranges), K_(task_id));
TO_STRING_KV(K_(ranges), K_(ss_ranges), K_(task_id));
public:
common::ObSEArray<common::ObNewRange, 1> ranges_;
common::ObSEArray<common::ObNewRange, 1> ss_ranges_;
ObDASTabletLoc *tablet_loc_;
//just for print
int64_t task_id_;

View File

@ -17,6 +17,7 @@
#include "sql/optimizer/ob_storage_estimator.h"
#include "share/stat/ob_opt_stat_manager.h"
#include "sql/engine/table/ob_table_scan_op.h"
#include "ob_opt_est_parameter_normal.h"
namespace oceanbase {
using namespace share::schema;
using namespace share;
@ -354,11 +355,16 @@ int ObAccessPathEstimation::estimate_prefix_range_rowcount(
logical_row_count *= est_cost_info.pushdown_prefix_filter_sel_;
physical_row_count *= est_cost_info.pushdown_prefix_filter_sel_;
// skip scan postfix range conditions
logical_row_count *= est_cost_info.ss_postfix_range_filters_sel_;
physical_row_count *= est_cost_info.ss_postfix_range_filters_sel_;
LOG_TRACE("OPT:[STORAGE EST ROW COUNT]",
K(logical_row_count), K(physical_row_count),
K(get_range_count), K(scan_range_count),
K(range_sample_ratio), K(result), K(est_cost_info.index_meta_info_.index_part_count_),
K(est_cost_info.pushdown_prefix_filter_sel_));
K(est_cost_info.pushdown_prefix_filter_sel_),
K(est_cost_info.ss_postfix_range_filters_sel_));
return ret;
}
@ -404,7 +410,15 @@ int ObAccessPathEstimation::fill_cost_table_scan_info(ObCostTableScanInfo &est_c
* est_cost_info.postfix_filter_sel_
* est_cost_info.table_filter_sel_;
if (OB_SUCC(ret)) {
if (OB_FAIL(ret)) {
} else if (!est_cost_info.ss_ranges_.empty()) {
int64_t scan_range_count = get_scan_range_count(est_cost_info.ss_ranges_);
if (scan_range_count == 1) {
est_cost_info.batch_type_ = ObSimpleBatch::T_MULTI_SCAN;
} else {
est_cost_info.batch_type_ = ObSimpleBatch::T_MULTI_GET;
}
} else {
int64_t get_range_count = get_get_range_count(est_cost_info.ranges_);
int64_t scan_range_count = get_scan_range_count(est_cost_info.ranges_);
if (get_range_count + scan_range_count > 1) {
@ -506,6 +520,12 @@ int ObAccessPathEstimation::process_statistics_estimation(const ObTableMetaInfo
path->est_cost_info_,
path->parent_->get_plan()->get_predicate_selectivities()))) {
LOG_WARN("failed to calculate filter selectivity", K(ret));
} else if (OB_FAIL(calc_skip_scan_prefix_ndv(*path, path->est_cost_info_.ss_prefix_ndv_))) {
LOG_WARN("failed to calc skip scan prefix ndv", K(ret));
} else if (OB_FAIL(update_use_skip_scan(path->est_cost_info_,
path->parent_->get_plan()->get_predicate_selectivities(),
path->use_skip_scan_))) {
LOG_WARN("failed to update use skip scan", K(ret));
} else {
ObArenaAllocator allocator;
ObCostTableScanInfo &est_cost_info = path->est_cost_info_;
@ -533,9 +553,14 @@ int ObAccessPathEstimation::process_statistics_estimation(const ObTableMetaInfo
logical_row_count *= est_cost_info.pushdown_prefix_filter_sel_;
physical_row_count *= est_cost_info.pushdown_prefix_filter_sel_;
// skip scan postfix range conditions
logical_row_count *= est_cost_info.ss_postfix_range_filters_sel_;
physical_row_count *= est_cost_info.ss_postfix_range_filters_sel_;
LOG_TRACE("OPT:[STATISTIC EST ROW COUNT",
K(logical_row_count), K(physical_row_count),
K(est_cost_info.pushdown_prefix_filter_sel_));
K(est_cost_info.pushdown_prefix_filter_sel_),
K(est_cost_info.ss_postfix_range_filters_sel_));
RowCountEstMethod est_method = meta.has_opt_stat_ ? RowCountEstMethod::BASIC_STAT :
RowCountEstMethod::DEFAULT_STAT;
@ -550,6 +575,137 @@ int ObAccessPathEstimation::process_statistics_estimation(const ObTableMetaInfo
return ret;
}
// calculate skip scan prefix range columns NDV and postfix range conditions selectivity.
// use the table_metas and origin_rows after extract prefix range.
int ObAccessPathEstimation::calc_skip_scan_prefix_ndv(AccessPath &ap, double &prefix_ndv)
{
int ret = OB_SUCCESS;
prefix_ndv = 1.0;
ObJoinOrder *join_order = NULL;
ObLogPlan *log_plan = NULL;
const ObTableMetaInfo *table_meta_info = NULL;
if (OB_ISNULL(ap.pre_query_range_) || !ap.pre_query_range_->is_ss_range()) {
/* do nothing */
} else if (OB_ISNULL(join_order = ap.parent_) || OB_ISNULL(log_plan = join_order->get_plan())
|| OB_ISNULL(table_meta_info = ap.est_cost_info_.table_meta_info_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(join_order), K(log_plan), K(table_meta_info));
} else {
// generate temporary update table metas use prefix range conditions
SMART_VAR(OptTableMetas, tmp_metas) {
ObSEArray<ObRawExpr*, 4> prefix_exprs;
const double prefix_range_row_count = table_meta_info->table_row_count_
* ap.est_cost_info_.prefix_filter_sel_
* ap.est_cost_info_.pushdown_prefix_filter_sel_;
log_plan->get_selectivity_ctx().init_op_ctx(&join_order->get_output_equal_sets(), prefix_range_row_count);
if (OB_FAIL(get_skip_scan_prefix_exprs(ap.est_cost_info_.range_columns_,
ap.pre_query_range_->get_skip_scan_offset(),
prefix_exprs))) {
LOG_WARN("failed to get skip scan prefix expers", K(ret));
} else if (OB_FAIL(ObOptSelectivity::update_table_meta_info(log_plan->get_basic_table_metas(),
tmp_metas,
log_plan->get_selectivity_ctx(),
ap.get_table_id(),
prefix_range_row_count,
ap.pre_query_range_->get_range_exprs(),
log_plan->get_predicate_selectivities()))) {
LOG_WARN("failed to update table meta info", K(ret));
} else if (OB_FAIL(ObOptSelectivity::calculate_distinct(tmp_metas,
log_plan->get_selectivity_ctx(),
prefix_exprs,
prefix_range_row_count,
prefix_ndv))) {
LOG_WARN("failed to calculate distinct", K(ret), K(prefix_exprs));
} else {
double refine_ndv = 1.0;
prefix_ndv = std::max(refine_ndv, prefix_ndv);
}
}
}
return ret;
}
int ObAccessPathEstimation::get_skip_scan_prefix_exprs(ObIArray<ColumnItem> &column_items,
int64_t skip_scan_offset,
ObIArray<ObRawExpr*> &prefix_exprs)
{
int ret = OB_SUCCESS;
prefix_exprs.reuse();
if (OB_UNLIKELY(skip_scan_offset < 0 || skip_scan_offset >= column_items.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected params", K(ret), K(skip_scan_offset), K(column_items.count()));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < skip_scan_offset; ++i) {
if (OB_FAIL(prefix_exprs.push_back(column_items.at(i).expr_))) {
LOG_WARN("failed to push back", K(ret), K(skip_scan_offset));
}
}
}
return ret;
}
int ObAccessPathEstimation::update_use_skip_scan(ObCostTableScanInfo &est_cost_info,
ObIArray<ObExprSelPair> &all_predicate_sel,
OptSkipScanState &use_skip_scan)
{
int ret = OB_SUCCESS;
const ObTableMetaInfo *table_meta_info = NULL;
if (OB_ISNULL(table_meta_info = est_cost_info.table_meta_info_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(table_meta_info));
} else {
// const static double NORMAL_CPU_TUPLE_COST = 0.02977945030613315927249275026;
// const static double NORMAL_TABLE_SCAN_CPU_TUPLE_COST = 0.3717749711890249146505031527;
// const static double NORMAL_MICRO_BLOCK_SEQ_COST = 4.12032943880540981;
// const static double NORMAL_MICRO_BLOCK_RND_COST = 5.45276187553;
const double row_count = table_meta_info->table_row_count_
* est_cost_info.prefix_filter_sel_
* est_cost_info.pushdown_prefix_filter_sel_;
const double row_count_per_range = std::max(row_count
* est_cost_info.ss_postfix_range_filters_sel_
/ est_cost_info.ss_prefix_ndv_,
1.0);
const double ss_row_count = est_cost_info.ss_prefix_ndv_
+ row_count_per_range * est_cost_info.ss_prefix_ndv_;
const double index_scan_cost = row_count * (NORMAL_CPU_TUPLE_COST + NORMAL_TABLE_SCAN_CPU_TUPLE_COST);
const double skip_scan_cost = ss_row_count * NORMAL_MICRO_BLOCK_RND_COST;
LOG_TRACE("decide use skip scan by ndv and selectively", K(use_skip_scan), K(row_count), K(row_count_per_range),
K(ss_row_count), K(index_scan_cost), K(skip_scan_cost),
K(est_cost_info.ss_prefix_ndv_), K(est_cost_info.ss_postfix_range_filters_sel_),
K(est_cost_info.ss_postfix_range_filters_));
bool reset_skip_scan = false;
if (OptSkipScanState::SS_UNSET != use_skip_scan) {
/* do nothing */
} else if (!table_meta_info->has_opt_stat_ ||
OB_DEFAULT_STAT_EST == table_meta_info->cost_est_type_) {
reset_skip_scan = true;
} else if (est_cost_info.ss_prefix_ndv_ > 1000 || est_cost_info.ss_postfix_range_filters_sel_ > 0.01) {
reset_skip_scan = true;
} else if (skip_scan_cost < index_scan_cost) {
use_skip_scan = OptSkipScanState::SS_NDV_SEL_ENABLE;
} else {
reset_skip_scan = true;
}
if (OB_FAIL(ret) || !reset_skip_scan) {
} else if (OB_FAIL(append(est_cost_info.postfix_filters_, est_cost_info.ss_postfix_range_filters_))) {
LOG_WARN("failed to append exprs", K(ret));
} else if (OB_FAIL(ObOptSelectivity::calculate_selectivity(*est_cost_info.table_metas_,
*est_cost_info.sel_ctx_,
est_cost_info.postfix_filters_,
est_cost_info.postfix_filter_sel_,
all_predicate_sel))) {
LOG_WARN("failed to calculate selectivity", K(est_cost_info.postfix_filters_), K(ret));
} else {
est_cost_info.ss_ranges_.reuse();
est_cost_info.ss_postfix_range_filters_.reuse();
est_cost_info.ss_prefix_ndv_ = 1.0;
est_cost_info.ss_postfix_range_filters_sel_ = 1.0;
use_skip_scan = OptSkipScanState::SS_DISABLE;
}
}
return ret;
}
int ObAccessPathEstimation::get_task(ObIArray<ObBatchEstTasks *> &tasks,
const ObAddr &addr,
ObBatchEstTasks *&task)

View File

@ -15,6 +15,7 @@
#include "sql/optimizer/ob_opt_est_cost.h"
#include "sql/optimizer/ob_optimizer_context.h"
#include "sql/optimizer/ob_join_order.h"
namespace oceanbase {
namespace sql {
class AccessPath;
@ -69,6 +70,16 @@ private:
ObTableMetaInfo &meta,
ObIArray<AccessPath *>& paths);
static int calc_skip_scan_prefix_ndv(AccessPath &ap, double &prefix_ndv);
static int get_skip_scan_prefix_exprs(ObIArray<ColumnItem> &column_items,
int64_t skip_scan_offset,
ObIArray<ObRawExpr*> &prefix_exprs);
static int update_use_skip_scan(ObCostTableScanInfo &est_cost_info,
ObIArray<ObExprSelPair> &all_predicate_sel,
OptSkipScanState &use_skip_scan);
static int do_storage_estimation(ObOptimizerContext &ctx,
ObBatchEstTasks &tasks);

View File

@ -28,6 +28,7 @@ public:
contain_always_false_(false),
query_range_(NULL),
ranges_(),
ss_ranges_(),
equal_prefix_count_(0),
equal_prefix_null_count_(0),
range_prefix_count_(0),
@ -48,6 +49,8 @@ public:
bool get_contain_always_false() const { return contain_always_false_; }
ObQueryRangeArray& get_ranges() { return ranges_; }
ObQueryRangeArray& get_ss_ranges() { return ss_ranges_; }
const ObQueryRangeArray& get_ss_ranges() const { return ss_ranges_; }
void set_query_range(ObQueryRange *query_range) { query_range_ = query_range; }
common::ObIArray<ColumnItem> &get_range_columns() { return range_columns_; }
common::ObIArray<ObExprConstraint> &get_expr_constraints() { return expr_constraints_; }
@ -88,6 +91,7 @@ private:
bool contain_always_false_;
ObQueryRange *query_range_;
ObQueryRangeArray ranges_;
ObQueryRangeArray ss_ranges_; // for index skip scan, postfix range
int64_t equal_prefix_count_;
int64_t equal_prefix_null_count_;
int64_t range_prefix_count_;

View File

@ -63,11 +63,14 @@ ObJoinOrder::~ObJoinOrder()
}
int ObJoinOrder::fill_query_range_info(const QueryRangeInfo &range_info,
ObCostTableScanInfo &est_cost_info)
ObCostTableScanInfo &est_cost_info,
bool use_skip_scan)
{
int ret = OB_SUCCESS;
const ObQueryRangeArray &ranges = range_info.get_ranges();
const ObQueryRangeArray &ss_ranges = range_info.get_ss_ranges();
est_cost_info.ranges_.reset();
est_cost_info.ss_ranges_.reset();
// maintain query range info
for(int64_t i = 0; OB_SUCC(ret) && i < ranges.count(); ++i) {
if (OB_ISNULL(ranges.at(i))) {
@ -77,6 +80,14 @@ int ObJoinOrder::fill_query_range_info(const QueryRangeInfo &range_info,
LOG_WARN("failed to add range", K(ret));
} else { /*do nothing*/ }
}
for(int64_t i = 0; use_skip_scan && OB_SUCC(ret) && i < ss_ranges.count(); ++i) {
if (OB_ISNULL(ss_ranges.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("range is null", K(ret));
} else if (OB_FAIL(est_cost_info.ss_ranges_.push_back(*ss_ranges.at(i)))) {
LOG_WARN("failed to add range", K(ret));
} else { /*do nothing*/ }
}
return ret;
}
@ -640,6 +651,7 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
ObQueryRange *query_range = NULL;
const share::schema::ObTableSchema *index_schema = NULL;
ObQueryRangeArray &ranges = range_info.get_ranges();
ObQueryRangeArray &ss_ranges = range_info.get_ss_ranges();
ObIArray<ColumnItem> &range_columns = range_info.get_range_columns();
bool is_geo_index = false;
ColumnIdInfoMap geo_columnInfo_map;
@ -678,7 +690,7 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
if (!is_geo_index && OB_FAIL(extract_preliminary_query_range(range_columns,
helper.filters_,
range_info.get_expr_constraints(),
query_range))) {
query_range))) {
LOG_WARN("failed to extract query range", K(ret), K(index_id));
} else if (is_geo_index && OB_FAIL(extract_geo_preliminary_query_range(range_columns,
helper.filters_,
@ -694,6 +706,11 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
all_single_value_range,
dtc_params))) {
LOG_WARN("failed to final extract query range", K(ret));
} else if (OB_FAIL(query_range->get_ss_tablet_ranges(*allocator_,
*exec_ctx,
ss_ranges,
dtc_params))) {
LOG_WARN("failed to final extract index skip query range", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::check_prefix_ranges_count(range_info.get_ranges(),
equal_prefix_count,
equal_prefix_null_count,
@ -723,7 +740,8 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
query_range = NULL;
}
} else {
LOG_TRACE("succeed to get query range", K(ranges), K(*query_range), K(table_id), K(index_id));
LOG_TRACE("succeed to get query range", K(ranges), K(ss_ranges), K(*query_range),
K(table_id), K(index_id));
}
}
return ret;
@ -865,7 +883,8 @@ int ObJoinOrder::add_table_by_heuristics(const uint64_t table_id,
index_info_cache,
helper,
das_access_path,
true))) {
true,
OptSkipScanState::SS_DISABLE))) {
LOG_WARN("failed to create primary index path", K(ret), K(table_id), K(ref_table_id));
} else if (OB_NOT_NULL(das_access_path) && OB_FAIL(access_paths.push_back(das_access_path))) {
LOG_WARN("failed to push back access path");
@ -876,7 +895,8 @@ int ObJoinOrder::add_table_by_heuristics(const uint64_t table_id,
index_info_cache,
helper,
basic_access_path,
false))) {
false,
OptSkipScanState::SS_DISABLE))) {
LOG_WARN("failed to make index path", "index_table_id", index_to_use, K(ret));
} else if (OB_NOT_NULL(basic_access_path) && OB_FAIL(access_paths.push_back(basic_access_path))) {
LOG_WARN("failed to create primary index path", K(ret), K(table_id), K(ref_table_id));
@ -1280,14 +1300,15 @@ int ObJoinOrder::will_use_das(const uint64_t table_id,
}
return ret;
}
int ObJoinOrder::create_one_access_path(const uint64_t table_id,
const uint64_t ref_id,
const uint64_t index_id,
const ObIndexInfoCache &index_info_cache,
PathHelper &helper,
AccessPath *&access_path,
bool use_das)
bool use_das,
OptSkipScanState use_skip_scan)
{
int ret = OB_SUCCESS;
IndexInfoEntry *index_info_entry = NULL;
@ -1350,6 +1371,7 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
ap->range_prefix_count_ = index_info_entry->get_range_info().get_range_prefix_count();
ap->interesting_order_info_ = index_info_entry->get_interesting_order_info();
ap->for_update_ = table_item->for_update_;
ap->use_skip_scan_ = use_skip_scan;
if (!get_plan()->get_stmt()->is_select_stmt()) {
// do nothing
// sample scan doesn't support DML other than SELECT.
@ -1398,7 +1420,8 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
LOG_WARN("failed to get index keys", K(ret));
} else if (OB_FAIL(ap->est_cost_info_.range_columns_.assign(range_info.get_range_columns()))) {
LOG_WARN("failed to assign range columns", K(ret));
} else if (OB_FAIL(fill_query_range_info(range_info, ap->est_cost_info_))) {
} else if (OB_FAIL(fill_query_range_info(range_info, ap->est_cost_info_,
OptSkipScanState::SS_DISABLE != use_skip_scan))) {
LOG_WARN("failed to fill query range info", K(ret));
} else { /*do nothing*/ }
} else { /*do nothing*/ }
@ -1417,7 +1440,8 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
ap->pre_query_range_,
ap->est_cost_info_,
is_nl_with_extended_range,
ObSqlSchemaGuard::is_link_table(get_plan()->get_stmt(), table_id)))) {
ObSqlSchemaGuard::is_link_table(get_plan()->get_stmt(), table_id),
OptSkipScanState::SS_DISABLE != use_skip_scan))) {
LOG_WARN("failed to fill filters for cost table info", K(ret));
} else if (!helper.is_inner_path_ &&
OB_FAIL(increase_diverse_path_count(ap))) {
@ -2039,6 +2063,7 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id,
bool is_create_das_path = false;
AccessPath *das_access_path = NULL;
AccessPath *basic_access_path = NULL; // the path does not use DAS, maybe optimal sometime.
OptSkipScanState use_skip_scan = OptSkipScanState::SS_UNSET;
if (OB_FAIL(will_use_das(table_id,
ref_table_id,
skyline_index_ids.at(i),
@ -2047,6 +2072,13 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id,
is_create_das_path,
is_create_basic_path))) {
LOG_WARN("failed to check will use das", K(ret));
} else if (OB_FAIL(will_use_skip_scan(table_id,
ref_table_id,
skyline_index_ids.at(i),
index_info_cache,
helper,
use_skip_scan))) {
LOG_WARN("failed to check will use skip scan", K(ret));
} else if (is_create_das_path &&
OB_FAIL(create_one_access_path(table_id,
ref_table_id,
@ -2054,7 +2086,8 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id,
index_info_cache,
helper,
das_access_path,
true))) {
true,
use_skip_scan))) {
LOG_WARN("failed to make index path", "index_table_id", skyline_index_ids.at(i), K(ret));
} else if ( OB_NOT_NULL(das_access_path) && OB_FAIL(access_paths.push_back(das_access_path))) {
LOG_WARN("failed to push back access path", K(ret));
@ -2065,7 +2098,8 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id,
index_info_cache,
helper,
basic_access_path,
false))) {
false,
use_skip_scan))) {
LOG_WARN("failed to make index path", "index_table_id", skyline_index_ids.at(i), K(ret));
} else if( OB_NOT_NULL(basic_access_path) && OB_FAIL(access_paths.push_back(basic_access_path))) {
LOG_WARN("failed to push back access path", K(ret));
@ -2075,6 +2109,55 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id,
return ret;
}
int ObJoinOrder::will_use_skip_scan(const uint64_t table_id,
const uint64_t ref_id,
const uint64_t index_id,
const ObIndexInfoCache &index_info_cache,
PathHelper &helper,
OptSkipScanState &use_skip_scan)
{
int ret = OB_SUCCESS;
use_skip_scan = OptSkipScanState::SS_UNSET;
IndexInfoEntry *index_info_entry = NULL;
const ObQueryRange *query_range = NULL;
bool hint_force_skip_scan = false;
bool hint_force_no_skip_scan = false;
if (OB_UNLIKELY(OB_INVALID_ID == ref_id) || OB_UNLIKELY(OB_INVALID_ID == index_id) ||
OB_ISNULL(get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ref_id), K(index_id), K(get_plan()), K(ret));
} else if (is_virtual_table(ref_id)) {
use_skip_scan = OptSkipScanState::SS_DISABLE;
} else if (OB_FAIL(index_info_cache.get_index_info_entry(table_id, index_id,
index_info_entry))) {
LOG_WARN("failed to get index info entry", K(table_id), K(index_id), K(ret));
} else if (OB_ISNULL(index_info_entry)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index info entry should not be null", K(ret));
} else if (OB_ISNULL(query_range = index_info_entry->get_range_info().get_query_range()) ||
!query_range->is_ss_range()) {
use_skip_scan = OptSkipScanState::SS_DISABLE;
} else if (OB_FAIL(get_plan()->get_log_plan_hint().check_use_skip_scan(table_id,
index_id,
hint_force_skip_scan,
hint_force_no_skip_scan))) {
LOG_WARN("failed to check use skip scan", K(ret), K(table_id));
} else if (hint_force_skip_scan) {
use_skip_scan = OptSkipScanState::SS_HINT_ENABLE;
} else if (hint_force_no_skip_scan) {
use_skip_scan = OptSkipScanState::SS_DISABLE;
} else if (helper.is_inner_path_ || get_tables().is_subset(get_plan()->get_subq_pdfilter_tset())) {
use_skip_scan = OptSkipScanState::SS_DISABLE;
} else {
// may use skip scan for SS_NDV_SEL_ENABLE after calculate ndv and selectivity
use_skip_scan = OptSkipScanState::SS_UNSET;
}
LOG_TRACE("check use skip scan", K(helper.is_inner_path_),
K(hint_force_skip_scan), K(hint_force_no_skip_scan), K(use_skip_scan));
return ret;
}
int ObJoinOrder::extract_param_for_query_range(const ObIArray<ObRawExpr*> &range_conditions,
ObIArray<int64_t> &param_pos)
{
@ -2199,7 +2282,7 @@ int ObJoinOrder::get_valid_index_ids(const uint64_t table_id,
LOG_WARN("failed to push back array", K(ret));
} else { /*do nothing*/ }
} else if (FALSE_IT(log_table_hint = get_plan()->get_log_plan_hint().get_index_hint(table_id))) {
} else if (NULL != log_table_hint && !log_table_hint->is_no_index_hint()) {
} else if (NULL != log_table_hint && log_table_hint->is_use_index_hint()) {
// for use index hint, get index ids from hint.
if (OB_FAIL(valid_index_ids.assign(log_table_hint->index_list_))) {
LOG_WARN("failed to assign index ids", K(ret));
@ -4050,6 +4133,7 @@ int AccessPath::assign(const AccessPath &other, common::ObIAllocator *allocator)
range_prefix_count_ = other.range_prefix_count_;
table_opt_info_ = other.table_opt_info_;
for_update_ = other.for_update_;
use_skip_scan_ = other.use_skip_scan_;
if (OB_ISNULL(allocator)) {
ret = OB_INVALID_ARGUMENT;
@ -4177,7 +4261,7 @@ int AccessPath::re_estimate_cost(EstimateCostInfo &param, double &card, double &
return ret;
}
const ObRangesArray& AccessPath::get_query_ranges() const
const ObIArray<ObNewRange>& AccessPath::get_query_ranges() const
{
return est_cost_info_.ranges_;
}
@ -9448,7 +9532,8 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
const ObQueryRange *query_range,
ObCostTableScanInfo &est_cost_info,
bool &is_nl_with_extended_range,
bool is_link)
bool is_link,
bool use_skip_scan)
{
int ret = OB_SUCCESS;
is_nl_with_extended_range = false;
@ -9493,6 +9578,8 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
if (OB_SUCC(ret)) {
if (OB_FAIL(est_cost_info.prefix_filters_.assign(query_range->get_range_exprs()))) {
LOG_WARN("failed to assign exprs", K(ret));
} else if (use_skip_scan && OB_FAIL(est_cost_info.ss_postfix_range_filters_.assign(query_range->get_ss_range_exprs()))) {
LOG_WARN("failed to assign exprs", K(ret));
}
}
@ -9568,7 +9655,9 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
} else if (can_extract) {
ret = est_cost_info.pushdown_prefix_filters_.push_back(filter);
} else if (est_cost_info.ref_table_id_ != est_cost_info.index_id_) {
ret = est_cost_info.postfix_filters_.push_back(filter);
if (!use_skip_scan || !ObOptimizerUtil::find_item(est_cost_info.ss_postfix_range_filters_, filter)) {
ret = est_cost_info.postfix_filters_.push_back(filter);
}
// 对于空间索引,空间谓词一定要回表计算
if (OB_SUCC(ret) && est_cost_info.index_meta_info_.is_geo_index_) {
ret = est_cost_info.table_filters_.push_back(filter);
@ -9607,7 +9696,8 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
is_nl_with_extended_range = true;
}
LOG_TRACE("succeed to classify filters", K(est_cost_info.prefix_filters_),
K(est_cost_info.pushdown_prefix_filters_), K(est_cost_info.postfix_filters_),
K(est_cost_info.pushdown_prefix_filters_), K(est_cost_info.ss_postfix_range_filters_),
K(est_cost_info.postfix_filters_),
K(est_cost_info.table_filters_), K(is_nl_with_extended_range));
}
}
@ -9968,19 +10058,17 @@ int ObJoinOrder::init_est_sel_info_for_access_path(const uint64_t table_id,
int ret = OB_SUCCESS;
ObSEArray<ObColumnRefRawExpr*, 16> column_exprs;
ObSEArray<uint64_t, 16> column_ids;
const ObDMLStmt *stmt = NULL;
ObSQLSessionInfo *session_info = NULL;
if (OB_UNLIKELY(OB_INVALID_ID == table_id) ||
OB_UNLIKELY(OB_INVALID_ID == ref_table_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid table id", K(table_id), K(ref_table_id), K(ret));
} else if (OB_ISNULL(get_plan()) ||
OB_ISNULL(stmt = get_plan()->get_stmt()) ||
OB_ISNULL(table_partition_info_) ||
OB_ISNULL(session_info = get_plan()->get_optimizer_context().get_session_info())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid params", K(get_plan()), K(ret));
} else if (OB_FAIL(stmt->get_column_exprs(table_id, column_exprs))) {
} else if (OB_FAIL(get_plan()->get_column_exprs(table_id, column_exprs))) {
LOG_WARN("failed to get column exprs", K(ret));
} else {
ObSEArray<int64_t, 64> all_used_part_id;

View File

@ -497,6 +497,14 @@ struct EstimateCostInfo {
DISALLOW_COPY_AND_ASSIGN(Path);
};
enum OptSkipScanState
{
SS_DISABLE = 0,
SS_UNSET,
SS_HINT_ENABLE,
SS_NDV_SEL_ENABLE
};
class AccessPath : public Path
{
public:
@ -529,7 +537,8 @@ struct EstimateCostInfo {
est_records_(),
range_prefix_count_(0),
table_opt_info_(),
for_update_(false)
for_update_(false),
use_skip_scan_(OptSkipScanState::SS_UNSET)
{
}
virtual ~AccessPath() {
@ -562,7 +571,7 @@ struct EstimateCostInfo {
return NULL == table_opt_info_ ? false :
OptimizationMethod::RULE_BASED != table_opt_info_->optimization_method_;
}
const ObRangesArray &get_query_ranges() const;
const ObIArray<ObNewRange> &get_query_ranges() const;
virtual void get_name_internal(char *buf, const int64_t buf_len, int64_t &pos) const
{
BUF_PRINTF("@");
@ -589,7 +598,8 @@ struct EstimateCostInfo {
K_(sample_info),
K_(range_prefix_count),
K_(for_update),
K_(use_das));
K_(use_das),
K_(use_skip_scan));
public:
//member variables
uint64_t table_id_;
@ -616,6 +626,7 @@ struct EstimateCostInfo {
int64_t range_prefix_count_; // prefix count
BaseTableOptInfo *table_opt_info_;
bool for_update_;
OptSkipScanState use_skip_scan_;
private:
DISALLOW_COPY_AND_ASSIGN(AccessPath);
};
@ -1335,7 +1346,8 @@ struct NullAwareAntiJoinInfo {
const ObIndexInfoCache &index_info_cache,
PathHelper &helper,
AccessPath *&ap,
bool use_das);
bool use_das,
OptSkipScanState use_skip_scan);
int will_use_das(const uint64_t table_id,
const uint64_t ref_id,
@ -1345,6 +1357,13 @@ struct NullAwareAntiJoinInfo {
bool &create_das_path,
bool &create_basic_path);
int will_use_skip_scan(const uint64_t table_id,
const uint64_t ref_id,
const uint64_t index_id,
const ObIndexInfoCache &index_info_cache,
PathHelper &helper,
OptSkipScanState &use_skip_scan);
int get_access_path_ordering(const uint64_t table_id,
const uint64_t ref_table_id,
const uint64_t index_id,
@ -1891,7 +1910,8 @@ struct NullAwareAntiJoinInfo {
const common::ObIArray<ObRawExpr*> &where_conditions);
int fill_query_range_info(const QueryRangeInfo &range_info,
ObCostTableScanInfo &est_cost_info);
ObCostTableScanInfo &est_cost_info,
bool use_skip_scan);
int compute_table_location_for_paths(ObIArray<AccessPath *> &access_paths,
ObIArray<ObTablePartitionInfo*> &tbl_part_infos);
@ -2067,7 +2087,8 @@ struct NullAwareAntiJoinInfo {
const ObQueryRange* query_range,
ObCostTableScanInfo &est_scan_cost_info,
bool &is_nl_with_extended_range,
bool is_link = false);
bool is_link = false,
bool use_skip_scan = false);
int can_extract_unprecise_range(const uint64_t table_id,
const ObRawExpr *filter,

View File

@ -4220,8 +4220,10 @@ int ObLogPlan::allocate_access_path(AccessPath *ap,
scan->set_index_back_row_count(ap->index_back_row_count_);
scan->set_estimate_method(ap->est_cost_info_.row_est_method_);
scan->set_pre_query_range(ap->pre_query_range_);
scan->set_skip_scan(OptSkipScanState::SS_DISABLE != ap->use_skip_scan_);
if (!ap->is_inner_path_ &&
OB_FAIL(scan->set_query_ranges(ap->get_cost_table_scan_info().ranges_))) {
OB_FAIL(scan->set_query_ranges(ap->get_cost_table_scan_info().ranges_,
ap->get_cost_table_scan_info().ss_ranges_))) {
LOG_WARN("failed to set query ranges", K(ret));
} else if (OB_FAIL(scan->set_range_columns(ap->get_cost_table_scan_info().range_columns_))) {
LOG_WARN("failed to set range column", K(ret));
@ -6715,7 +6717,9 @@ int ObLogPlan::check_scalar_groupby_pushdown(const ObIArray<ObAggFunRawExpr *> &
if (OB_ISNULL(cur_aggr = aggrs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (T_FUN_COUNT != cur_aggr->get_expr_type()) {
} else if (T_FUN_COUNT != cur_aggr->get_expr_type()
&& T_FUN_MIN != cur_aggr->get_expr_type()
&& T_FUN_MAX != cur_aggr->get_expr_type()) {
can_push = false;
} else if (cur_aggr->is_param_distinct() || 1 < cur_aggr->get_real_param_count()) {
/* mysql mode, support count(distinct c1, c2). if this distinct can be eliminated,
@ -11769,6 +11773,26 @@ const ColumnItem *ObLogPlan::get_column_item_by_id(uint64_t table_id, uint64_t c
return column_item;
}
int ObLogPlan::get_column_exprs(uint64_t table_id, ObIArray<ObColumnRefRawExpr*> &column_exprs) const
{
int ret = OB_SUCCESS;
if (OB_ISNULL(get_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(get_stmt()));
} else if (OB_FAIL(get_stmt()->get_column_exprs(table_id, column_exprs))) {
LOG_WARN("failed to get column exprs", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < column_items_.count(); ++i) {
if (table_id == column_items_.at(i).table_id_
&& OB_FAIL(column_exprs.push_back(column_items_.at(i).expr_))) {
LOG_WARN("failed to push back", K(ret));
}
}
}
return ret;
}
int ObLogPlan::generate_column_expr(ObRawExprFactory &expr_factory,
const uint64_t &table_id,
const ObColumnSchemaV2 &column_schema,

View File

@ -1279,6 +1279,9 @@ public:
uint64_t table_id,
const share::schema::ObTableSchema &index_table_schema,
common::ObIArray<ColumnItem> &index_columns);
int get_column_exprs(uint64_t table_id, ObIArray<ObColumnRefRawExpr*> &column_exprs) const;
ObColumnRefRawExpr *get_column_expr_by_id(uint64_t table_id, uint64_t column_id) const;
const ColumnItem *get_column_item_by_id(uint64_t table_id, uint64_t column_id) const;
inline common::ObIArray<ColumnItem> &get_column_items() { return column_items_; }
int generate_column_expr(ObRawExprFactory &expr_factory,
const uint64_t &table_id,
@ -1336,8 +1339,6 @@ public:
int allocate_material_for_recursive_cte_plan(ObIArray<ObLogicalOperator*> &child_ops);
protected:
ObColumnRefRawExpr *get_column_expr_by_id(uint64_t table_id, uint64_t column_id) const;
const ColumnItem *get_column_item_by_id(uint64_t table_id, uint64_t column_id) const;
int update_plans_interesting_order_info(ObIArray<CandidatePlan> &candidate_plans,
const int64_t check_scope);

72
src/sql/optimizer/ob_log_table_scan.cpp Normal file → Executable file
View File

@ -47,6 +47,8 @@ const char *ObLogTableScan::get_name() const
}
if (sample_method != SampleInfo::NO_SAMPLE) {
name = (sample_method == SampleInfo::ROW_SAMPLE) ? "ROW SAMPLE SCAN" : "BLOCK SAMPLE SCAN";
} else if (is_skip_scan()) {
name = use_das() ? "DISTRIBUTED INDEX SKIP SCAN" : "INDEX SKIP SCAN";
} else if (use_das()) {
name = is_get ? "DISTRIBUTED TABLE GET" : "DISTRIBUTED TABLE SCAN";
} else {
@ -1165,6 +1167,17 @@ int ObLogTableScan::print_range_annotation(char *buf,
ret = print_ranges(buf, buf_len, pos, ranges_);
}
if (OB_SUCC(ret) && is_skip_scan()) {
int64_t skip_scan_offset = get_pre_query_range()->get_skip_scan_offset();
if (OB_FAIL(BUF_PRINTF("\n prefix_columns_cnt = %ld , skip_scan_range", skip_scan_offset))) {
LOG_WARN("BUF_PRINTF fails", K(ret));
} else if (ss_ranges_.empty() && OB_FAIL(BUF_PRINTF("(MIN ; MAX)"))) {
LOG_WARN("BUF_PRINTF fails", K(ret));
} else if (OB_FAIL(print_ranges(buf, buf_len, pos, ss_ranges_))) {
LOG_WARN("failed to print index skip ranges", K(ret));
} else { /* Do nothing */ }
}
if (OB_SUCC(ret)) {
if (!range_conds_.empty()) {
//print range condition
@ -1204,11 +1217,14 @@ int ObLogTableScan::print_limit_offset_annotation(char *buf,
return ret;
}
int ObLogTableScan::set_query_ranges(ObRangesArray ranges)
int ObLogTableScan::set_query_ranges(ObIArray<ObNewRange> &ranges,
ObIArray<ObNewRange> &ss_ranges)
{
int ret = OB_SUCCESS;
if (OB_FAIL(append(ranges_, ranges))) {
LOG_WARN("Failed to do append to ranges_ in set_query_ranges()");
} else if (OB_FAIL(append(ss_ranges_, ss_ranges))) {
LOG_WARN("Failed to do append to ranges_ in set_query_ranges()");
} else { /* Do nothing =*/ }
return ret;
}
@ -1233,6 +1249,7 @@ int ObLogTableScan::print_used_hint(planText &plan_text)
const ObLogPlanHint &plan_hint = get_plan()->get_log_plan_hint();
const LogTableHint *table_hint = plan_hint.get_log_table_hint(table_id_);
const ObHint *hint = plan_hint.get_normal_hint(T_USE_LATE_MATERIALIZATION);
int64_t idx = OB_INVALID_INDEX;
if (NULL != hint
&& ((need_late_materialization() && hint->is_enable_hint()) ||
(!need_late_materialization() && hint->is_disable_hint()))
@ -1248,34 +1265,30 @@ int ObLogTableScan::print_used_hint(planText &plan_text)
LOG_WARN("failed to print table parallel hint", K(ret));
} else if (table_hint->index_list_.empty()) {
/*do nothing*/
} else if (OB_UNLIKELY(table_hint->index_list_.count() != table_hint->index_hints_.count()
|| (!table_hint->is_index_hint() && !table_hint->is_no_index_hint()))) {
} else if (OB_UNLIKELY(table_hint->index_list_.count() != table_hint->index_hints_.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected log index hint", K(ret), K(*table_hint));
} else {
int64_t idx = OB_INVALID_INDEX;
} else if (table_hint->is_use_index_hint()) {// print used use index hint
if (ObOptimizerUtil::find_item(table_hint->index_list_, index_table_id_, &idx)) {
if (OB_UNLIKELY(idx < 0 || idx >= table_hint->index_list_.count())
|| OB_ISNULL(hint = table_hint->index_hints_.at(idx))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected idx", K(ret), K(idx), K(table_hint->index_list_));
} else if (table_hint->is_index_hint() &&
OB_FAIL(hint->print_hint(plan_text))) {
} else if (!is_skip_scan() && T_INDEX_SS_HINT == hint->get_hint_type()) {
/* is not index skip scan but exist index_ss hint */
} else if (OB_FAIL(hint->print_hint(plan_text))) {
LOG_WARN("failed to print indedx hint", K(ret), K(*hint));
}
}
// print all no index
if (OB_SUCC(ret) && table_hint->is_no_index_hint()) {
for (int64_t i = 0 ; OB_SUCC(ret) && i < table_hint->index_list_.count(); ++i) {
if (idx == i) {
/*do nothing*/
} else if (OB_ISNULL(hint = table_hint->index_hints_.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected NULL", K(ret), K(hint));
} else if (OB_FAIL(hint->print_hint(plan_text))) {
LOG_WARN("failed to print indedx hint", K(ret), K(*hint));
}
} else {// print all no index
for (int64_t i = 0 ; OB_SUCC(ret) && i < table_hint->index_list_.count(); ++i) {
if (idx == i) {
/*do nothing*/
} else if (OB_ISNULL(hint = table_hint->index_hints_.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected NULL", K(ret), K(hint));
} else if (OB_FAIL(hint->print_hint(plan_text))) {
LOG_WARN("failed to print indedx hint", K(ret), K(*hint));
}
}
}
@ -1291,6 +1304,21 @@ int ObLogTableScan::print_outline_data(planText &plan_text)
int64_t &pos = plan_text.pos;
TableItem *table_item = NULL;
ObString qb_name;
const ObString *index_name = NULL;
ObItemType index_type = T_INDEX_HINT;
if (is_skip_scan()) {
index_type = T_INDEX_SS_HINT;
if (ref_table_id_ == index_table_id_) {
index_name = &ObIndexHint::PRIMARY_KEY;
} else {
index_name = &get_index_name();
}
} else if (ref_table_id_ == index_table_id_) {
index_type = T_FULL_HINT;
} else {
index_type = T_INDEX_HINT;
index_name = &get_index_name();
}
const ObDMLStmt *stmt = NULL;
const ObTableParallelHint *parallel_hint = NULL;
if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) {
@ -1325,11 +1353,11 @@ int ObLogTableScan::print_outline_data(planText &plan_text)
&& static_cast<ObLogJoin*>(get_parent())->is_late_mat()) {
// late materialization right table, do not print index hint.
} else {
ObIndexHint index_hint(ref_table_id_ == index_table_id_ ? T_FULL_HINT: T_INDEX_HINT);
ObIndexHint index_hint(index_type);
index_hint.set_qb_name(qb_name);
index_hint.get_table().set_table(*table_item);
if (T_INDEX_HINT == index_hint.get_hint_type()) {
index_hint.get_index_name().assign(get_index_name().ptr(), get_index_name().length());
if (NULL != index_name) {
index_hint.get_index_name().assign_ptr(index_name->ptr(), index_name->length());
}
if (OB_FAIL(index_hint.print_hint(plan_text))) {
LOG_WARN("failed to print index hint", K(ret));

View File

@ -51,6 +51,8 @@ public:
filter_before_index_back_(),
table_partition_info_(NULL),
ranges_(),
ss_ranges_(),
is_skip_scan_(),
limit_count_expr_(NULL),
limit_offset_expr_(NULL),
sample_info_(),
@ -314,6 +316,8 @@ public:
bool is_index_scan() const { return ref_table_id_ != index_table_id_; }
bool is_table_whole_range_scan() const { return !is_index_scan() && (NULL == pre_query_range_ ||
(1 == ranges_.count() && ranges_.at(0).is_whole_range())); }
void set_skip_scan(bool is_skip_scan) { is_skip_scan_ = is_skip_scan; }
bool is_skip_scan() const { return is_skip_scan_; }
virtual bool is_table_scan() const override { return true; }
bool is_whole_range_scan() const {return NULL == pre_query_range_
|| (1 == ranges_.count() && ranges_.at(0).is_whole_range()); }
@ -323,7 +327,7 @@ public:
void set_is_multi_part_table_scan(bool multi_part_tsc)
{ is_multi_part_table_scan_ = multi_part_tsc; }
bool get_is_multi_part_table_scan() { return is_multi_part_table_scan_; }
int set_query_ranges(ObRangesArray ranges);
int set_query_ranges(ObIArray<ObNewRange> &ranges, ObIArray<ObNewRange> &ss_ranges);
virtual int inner_replace_generated_agg_expr(
const common::ObIArray<std::pair<ObRawExpr *, ObRawExpr *> >&to_replace_exprs);
inline common::ObIArray<bool> &get_filter_before_index_flags() { return filter_before_index_back_; }
@ -487,6 +491,8 @@ protected: // memeber variables
//because its used in EXCHANGE stage, and
//copy_without_child used before this
ObRangesArray ranges_;//For explain. Code generator and executor cannot use this.
ObRangesArray ss_ranges_;//For explain. Code generator and executor cannot use this.
bool is_skip_scan_;
// limit params from upper limit op
ObRawExpr *limit_count_expr_;

View File

@ -605,6 +605,12 @@ int ObOptEstCost::calculate_filter_selectivity(ObCostTableScanInfo &est_cost_inf
est_cost_info.pushdown_prefix_filter_sel_,
all_predicate_sel))) {
LOG_WARN("failed to calculate selectivity", K(est_cost_info.pushdown_prefix_filters_), K(ret));
} else if (OB_FAIL(ObOptSelectivity::calculate_selectivity(*est_cost_info.table_metas_,
*est_cost_info.sel_ctx_,
est_cost_info.ss_postfix_range_filters_,
est_cost_info.ss_postfix_range_filters_sel_,
all_predicate_sel))) {
LOG_WARN("failed to calculate selectivity", K(est_cost_info.ss_postfix_range_filters_), K(ret));
} else if (OB_FAIL(ObOptSelectivity::calculate_selectivity(*est_cost_info.table_metas_,
*est_cost_info.sel_ctx_,
est_cost_info.postfix_filters_,
@ -622,6 +628,7 @@ int ObOptEstCost::calculate_filter_selectivity(ObCostTableScanInfo &est_cost_inf
K(est_cost_info.prefix_filters_), K(est_cost_info.pushdown_prefix_filters_),
K(est_cost_info.postfix_filters_), K(est_cost_info.table_filters_),
K(est_cost_info.prefix_filter_sel_), K(est_cost_info.pushdown_prefix_filter_sel_),
K(est_cost_info.ss_postfix_range_filters_), K(est_cost_info.ss_postfix_range_filters_sel_),
K(est_cost_info.postfix_filter_sel_), K(est_cost_info.table_filter_sel_));
}
return ret;

View File

@ -56,6 +56,8 @@ int ObCostTableScanInfo::assign(const ObCostTableScanInfo &est_cost_info)
pushdown_prefix_filter_sel_ = est_cost_info.pushdown_prefix_filter_sel_;
postfix_filter_sel_ = est_cost_info.postfix_filter_sel_;
table_filter_sel_ = est_cost_info.table_filter_sel_;
ss_prefix_ndv_ = est_cost_info.ss_prefix_ndv_;
ss_postfix_range_filters_sel_ = est_cost_info.ss_postfix_range_filters_sel_;
batch_type_ = est_cost_info.batch_type_;
sample_info_ = est_cost_info.sample_info_;
// no need to copy table scan param
@ -1243,38 +1245,71 @@ int ObOptEstCostModel::cost_table_one_batch(const ObCostTableScanInfo &est_cost_
double &index_back_cost)
{
int ret = OB_SUCCESS;
int64_t part_cnt = est_cost_info.index_meta_info_.index_part_count_;
double per_part_log_cnt = logical_row_count / part_cnt;
double per_part_phy_cnt = physical_row_count / part_cnt;
if (OB_UNLIKELY(logical_row_count < 0.0) || OB_UNLIKELY(parallel < 1)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("get unexpected error", K(logical_row_count), K(parallel), K(ret));
} else {
int64_t part_cnt = est_cost_info.index_meta_info_.index_part_count_;
double per_part_log_cnt = logical_row_count / part_cnt;
double per_part_phy_cnt = physical_row_count / part_cnt;
if (ObSimpleBatch::T_GET == type || ObSimpleBatch::T_MULTI_GET == type) {
if (OB_FAIL(cost_table_get_one_batch(est_cost_info,
per_part_log_cnt,
cost,
index_back_cost))) {
LOG_WARN("Failed to estimate get cost", K(ret));
} else {
cost = cost * part_cnt / parallel;
index_back_cost = index_back_cost * part_cnt / parallel;
}
} else if (ObSimpleBatch::T_SCAN == type || ObSimpleBatch::T_MULTI_SCAN == type) {
if (OB_FAIL(cost_table_scan_one_batch(est_cost_info,
per_part_log_cnt,
per_part_phy_cnt,
cost,
index_back_cost))) {
LOG_WARN("Failed to estimate scan cost", K(ret));
} else {
cost = cost * part_cnt / parallel;
index_back_cost = index_back_cost * part_cnt / parallel;
}
} else {
} else if (!est_cost_info.ss_ranges_.empty()) {
double ss_prefix_scan_cost = 0.0;
per_part_log_cnt /= est_cost_info.ss_prefix_ndv_;
per_part_phy_cnt /= est_cost_info.ss_prefix_ndv_;
if (OB_UNLIKELY(ObSimpleBatch::T_MULTI_GET != type && ObSimpleBatch::T_MULTI_SCAN != type)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid batch type", K(ret), K(type));
LOG_WARN("invalid skip scan batch type", K(ret), K(type));
} else if (OB_FAIL(cost_skip_scan_prefix_scan_one_row(est_cost_info, ss_prefix_scan_cost))) {
LOG_WARN("failed to calc skip scan prefix scan one row cost", K(ret), K(est_cost_info));
} else if (ObSimpleBatch::T_MULTI_GET == type
&& OB_FAIL(cost_table_get_one_batch(est_cost_info,
per_part_log_cnt,
cost,
index_back_cost))) {
LOG_WARN("Failed to estimate get cost", K(ret));
} else if (ObSimpleBatch::T_MULTI_SCAN == type
&& OB_FAIL(cost_table_scan_one_batch(est_cost_info,
per_part_log_cnt,
per_part_phy_cnt,
cost,
index_back_cost))) {
LOG_WARN("Failed to estimate scan cost", K(ret));
} else {
// cost table scan/get one batch
cost = cost * part_cnt / parallel;
index_back_cost = index_back_cost * part_cnt / parallel;
ss_prefix_scan_cost = ss_prefix_scan_cost * part_cnt / parallel;
// cost calculate skip scan prefix ndv
ss_prefix_scan_cost *= est_cost_info.ss_prefix_ndv_;
index_back_cost *= est_cost_info.ss_prefix_ndv_;
cost = cost * est_cost_info.ss_prefix_ndv_ + ss_prefix_scan_cost;
LOG_TRACE("OPT:[COST SKIP SCAN]", K(type), K(est_cost_info.ss_prefix_ndv_),
K(per_part_log_cnt), K(ss_prefix_scan_cost), K(cost));
}
} else if (ObSimpleBatch::T_GET == type || ObSimpleBatch::T_MULTI_GET == type) {
if (OB_FAIL(cost_table_get_one_batch(est_cost_info,
per_part_log_cnt,
cost,
index_back_cost))) {
LOG_WARN("Failed to estimate get cost", K(ret));
} else {
cost = cost * part_cnt / parallel;
index_back_cost = index_back_cost * part_cnt / parallel;
}
} else if (ObSimpleBatch::T_SCAN == type || ObSimpleBatch::T_MULTI_SCAN == type) {
if (OB_FAIL(cost_table_scan_one_batch(est_cost_info,
per_part_log_cnt,
per_part_phy_cnt,
cost,
index_back_cost))) {
LOG_WARN("Failed to estimate scan cost", K(ret));
} else {
cost = cost * part_cnt / parallel;
index_back_cost = index_back_cost * part_cnt / parallel;
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid batch type", K(ret), K(type));
}
return ret;
}
@ -1457,6 +1492,91 @@ int ObOptEstCostModel::cost_table_get_one_batch_spatial(double row_count,
return ret;
}
int ObOptEstCostModel::cost_skip_scan_prefix_scan_one_row(const ObCostTableScanInfo &est_cost_info,
double &cost)
{
int ret = OB_SUCCESS;
const ObTableMetaInfo *table_meta_info = est_cost_info.table_meta_info_;
const ObIndexMetaInfo &index_meta_info = est_cost_info.index_meta_info_;
const double row_count = 1.0;
double project_cost = 0.0;
if (OB_ISNULL(table_meta_info) ||
OB_UNLIKELY(table_meta_info->table_row_count_ <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid args", K(table_meta_info), K(ret));
} else if (OB_FAIL(cost_full_table_scan_project(row_count,
est_cost_info,
project_cost))) {
LOG_WARN("failed to cost project", K(ret));
} else {
//索引总的微块数 = 总大小/微块大小
double num_micro_blocks = index_meta_info.get_micro_block_numbers();
//读微块数 = 总微块数 * 读行比例
double num_micro_blocks_read = 0;
if (OB_LIKELY(table_meta_info->table_row_count_ > 0) &&
row_count <= table_meta_info->table_row_count_) {
num_micro_blocks_read = std::ceil(num_micro_blocks
* row_count
/ static_cast<double> (table_meta_info->table_row_count_));
} else {
num_micro_blocks_read = num_micro_blocks;
}
// revise number of rows if is row sample scan
// 对于行采样,除了微块扫描数外,其他按比例缩小
// if (est_cost_info.sample_info_.is_row_sample()) {
// row_count *= 0.01 * est_cost_info.sample_info_.percent_;
// }
// IO代价,主要包括读取微块、反序列化的代价的代价
double io_cost = 0.0;
double first_block_cost = cost_params_.MICRO_BLOCK_RND_COST;
double rows_in_one_block = static_cast<double> (table_meta_info->table_row_count_) / num_micro_blocks;
rows_in_one_block = rows_in_one_block <= 1 ? 1.000001 : rows_in_one_block;
if (!est_cost_info.pushdown_prefix_filters_.empty()) {
if (est_cost_info.can_use_batch_nlj_) {
first_block_cost = cost_params_.BATCH_NL_SCAN_COST;
} else {
first_block_cost = cost_params_.NL_SCAN_COST;
}
}
if (num_micro_blocks_read < 1) {
io_cost = first_block_cost;
} else {
io_cost = first_block_cost + cost_params_.MICRO_BLOCK_SEQ_COST * (num_micro_blocks_read-1);
}
// filter cost, skip scan prefix scan do not calculate filter now
double qual_cost = 0.0;
// ObSEArray<ObRawExpr*, 8> filters;
// if (OB_FAIL(append(filters, est_cost_info.ss_prefix_filters_))) { need get skip scan prefix filter can not extract prefix range
// LOG_WARN("failed to append fiilters", K(ret));
// } else {
// qual_cost += cost_quals(row_count, filters);
// }
// CPU代价,包括get_next_row调用的代价和谓词代价
double cpu_cost = row_count * cost_params_.CPU_TUPLE_COST + qual_cost;
// 从memtable读取数据的代价,待提供
double memtable_cost = 0;
// memtable数据和基线数据合并的代价,待提供
double memtable_merge_cost = 0;
//因为存储层有预期,所以去存储层的IO、CPU代价的最大值
double scan_cpu_cost = row_count * cost_params_.TABLE_SCAN_CPU_TUPLE_COST + project_cost;
cpu_cost += scan_cpu_cost;
if (io_cost > cpu_cost) {
cost = io_cost + memtable_cost + memtable_merge_cost;
} else {
cost = cpu_cost + memtable_cost + memtable_merge_cost;
}
LOG_TRACE("OPT:[COST SKIP SCAN PREFIX SCAN ONE ROW]", K(num_micro_blocks), K(table_meta_info->table_row_count_),
K(cost), K(io_cost), K(cpu_cost), K(memtable_cost), K(memtable_merge_cost), K(qual_cost),
K(project_cost), K(num_micro_blocks_read));
}
return ret;
}
/**
* TableScan的代价
* formula: cost = io_cost + memtable_cost + memtable_merge_cost + cpu_cost

View File

@ -182,9 +182,11 @@ struct ObCostTableScanInfo
is_inner_path_(false),
can_use_batch_nlj_(false),
ranges_(),
ss_ranges_(),
range_columns_(),
prefix_filters_(),
pushdown_prefix_filters_(),
ss_postfix_range_filters_(),
postfix_filters_(),
table_filters_(),
table_metas_(NULL),
@ -195,6 +197,8 @@ struct ObCostTableScanInfo
postfix_filter_sel_(1.0),
table_filter_sel_(1.0),
join_filter_sel_(1.0),
ss_prefix_ndv_(1.0),
ss_postfix_range_filters_sel_(1.0),
batch_type_(common::ObSimpleBatch::ObBatchType::T_NONE)
{ }
virtual ~ObCostTableScanInfo()
@ -208,7 +212,8 @@ struct ObCostTableScanInfo
K_(is_virtual_table), K_(is_unique),
K_(is_inner_path), K_(can_use_batch_nlj),
K_(prefix_filter_sel), K_(pushdown_prefix_filter_sel),
K_(postfix_filter_sel), K_(table_filter_sel));
K_(postfix_filter_sel), K_(table_filter_sel),
K_(ss_prefix_ndv), K_(ss_postfix_range_filters_sel));
// the following information need to be set before estimating cost
uint64_t table_id_; // table id
uint64_t ref_table_id_; // ref table id
@ -220,6 +225,7 @@ struct ObCostTableScanInfo
bool is_inner_path_;
bool can_use_batch_nlj_;
ObRangesArray ranges_; // all the ranges
ObRangesArray ss_ranges_; // skip scan ranges
common::ObSEArray<ColumnItem, 4, common::ModulePageAllocator, true> range_columns_; // all the range columns
common::ObSEArray<ColumnItem, 4, common::ModulePageAllocator, true> access_column_items_; // all the access columns
common::ObSEArray<ColumnItem, 4, common::ModulePageAllocator, true> index_access_column_items_; // all the access columns
@ -227,6 +233,7 @@ struct ObCostTableScanInfo
//这几个filter的分类参考OptimizerUtil::classify_filters()
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> prefix_filters_; // filters match index prefix
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> pushdown_prefix_filters_; // filters match index prefix along pushed down filter
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> ss_postfix_range_filters_; // range conditions extract postfix range for skip scan
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> postfix_filters_; // filters evaluated before index back, but not index prefix
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> table_filters_; // filters evaluated after index back
@ -241,6 +248,8 @@ struct ObCostTableScanInfo
double postfix_filter_sel_;
double table_filter_sel_;
double join_filter_sel_;
double ss_prefix_ndv_; // skip scan prefix columns NDV
double ss_postfix_range_filters_sel_;
common::ObSimpleBatch::ObBatchType batch_type_;
SampleInfo sample_info_;
private:
@ -1020,6 +1029,9 @@ protected:
const ObCostTableScanInfo &est_cost_info,
bool is_scan_index,
double &res);
int cost_skip_scan_prefix_scan_one_row(const ObCostTableScanInfo &est_cost_info,
double &cost);
protected:
const double (&comparison_params_)[common::ObMaxTC + 1];
const double (&hash_params_)[common::ObMaxTC + 1];

View File

@ -735,12 +735,12 @@ int ObOptSelectivity::update_table_meta_info(const OptTableMetas &base_table_met
int ret = OB_SUCCESS;
const OptTableMeta *base_table_meta = base_table_metas.get_table_meta_by_table_id(table_id);
OptTableMeta *table_meta = NULL;
const ObDMLStmt *stmt = NULL;
const ObLogPlan *log_plan = NULL;
ObSEArray<OptSelInfo, 8> column_sel_infos;
filtered_rows = filtered_rows < 1.0 ? 1.0 : filtered_rows;
if (OB_ISNULL(base_table_meta) || OB_ISNULL(stmt = ctx.get_stmt())) {
if (OB_ISNULL(base_table_meta) || OB_ISNULL(log_plan = ctx.get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(base_table_meta), K(stmt));
LOG_WARN("get unexpected null", K(ret), K(base_table_meta), K(log_plan));
} else if (OB_FAIL(update_table_metas.copy_table_meta_info(*base_table_meta, table_meta))) {
LOG_WARN("failed to copy table meta info", K(ret));
} else {
@ -794,7 +794,7 @@ int ObOptSelectivity::update_table_meta_info(const OptTableMetas &base_table_met
// update null number
if (null_num > 0) {
bool null_reject = false;
const ObColumnRefRawExpr *column_expr = stmt->get_column_expr_by_id(
const ObColumnRefRawExpr *column_expr = log_plan->get_column_expr_by_id(
table_meta->get_table_id(), column_meta.get_column_id());
if (OB_ISNULL(column_expr)) {
ret = OB_ERR_UNEXPECTED;
@ -3512,7 +3512,7 @@ int ObOptSelectivity::get_column_query_range(const OptSelectivityCtx &ctx,
ObQueryRangeArray &ranges)
{
int ret = OB_SUCCESS;
const ObDMLStmt *stmt = ctx.get_stmt();
const ObLogPlan *log_plan = ctx.get_plan();
const ParamStore *params = ctx.get_params();
ObExecContext *exec_ctx = ctx.get_opt_ctx().get_exec_ctx();
ObIAllocator &allocator = ctx.get_allocator();
@ -3520,10 +3520,10 @@ int ObOptSelectivity::get_column_query_range(const OptSelectivityCtx &ctx,
const ColumnItem* column_item = NULL;
ObGetMethodArray get_methods;
if (OB_ISNULL(stmt) || OB_ISNULL(exec_ctx) ||
OB_ISNULL(column_item = stmt->get_column_item_by_id(table_id, column_id))) {
if (OB_ISNULL(log_plan) || OB_ISNULL(exec_ctx) ||
OB_ISNULL(column_item = log_plan->get_column_item_by_id(table_id, column_id))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(stmt), K(exec_ctx), K(column_item));
LOG_WARN("get unexpected null", K(ret), K(log_plan), K(exec_ctx), K(column_item));
} else if (OB_FAIL(column_items.push_back(*column_item))) {
LOG_WARN("failed to push back column item", K(ret));
} else if (OB_FAIL(query_range.preliminary_extract_query_range(column_items,

3
src/sql/parser/sql_parser_mysql_mode.l Normal file → Executable file
View File

@ -881,6 +881,9 @@ Timestamp{whitespace}?\"[^\"]*\" {
<hint>NO_INDEX { return NO_INDEX_HINT; }
<hint>USE_DAS { return USE_DAS_HINT; }
<hint>NO_USE_DAS { return NO_USE_DAS_HINT; }
<hint>INDEX_SS { return INDEX_SS_HINT; }
<hint>INDEX_SS_ASC { return INDEX_SS_ASC_HINT; }
<hint>INDEX_SS_DESC { return INDEX_SS_DESC_HINT; }
<hint>USE_NL { return USE_NL; }
<hint>NO_USE_NL { return NO_USE_NL; }
<hint>USE_NL_MATERIALIZATION { return USE_NL_MATERIALIZATION; }

16
src/sql/parser/sql_parser_mysql_mode.y Normal file → Executable file
View File

@ -166,7 +166,9 @@ COALESCE_SQ NO_COALESCE_SQ COUNT_TO_EXISTS NO_COUNT_TO_EXISTS LEFT_TO_ANTI NO_LE
ELIMINATE_JOIN NO_ELIMINATE_JOIN PUSH_LIMIT NO_PUSH_LIMIT PULLUP_EXPR NO_PULLUP_EXPR
WIN_MAGIC NO_WIN_MAGIC
// optimize hint
INDEX_HINT FULL_HINT NO_INDEX_HINT USE_DAS_HINT NO_USE_DAS_HINT LEADING_HINT ORDERED
INDEX_HINT FULL_HINT NO_INDEX_HINT USE_DAS_HINT NO_USE_DAS_HINT
INDEX_SS_HINT INDEX_SS_ASC_HINT INDEX_SS_DESC_HINT
LEADING_HINT ORDERED
USE_NL USE_MERGE USE_HASH NO_USE_HASH NO_USE_MERGE NO_USE_NL
USE_NL_MATERIALIZATION NO_USE_NL_MATERIALIZATION
USE_HASH_AGGREGATION NO_USE_HASH_AGGREGATION
@ -8680,6 +8682,18 @@ INDEX_HINT '(' qb_name_option relation_factor_in_hint NAME_OB ')'
{
malloc_non_terminal_node($$, result->malloc_pool_, T_NO_USE_DAS_HINT, 2, $3, $4);
}
| INDEX_SS_HINT '(' qb_name_option relation_factor_in_hint NAME_OB ')'
{
malloc_non_terminal_node($$, result->malloc_pool_, T_INDEX_SS_HINT, 3, $3, $4, $5);
}
| INDEX_SS_ASC_HINT '(' qb_name_option relation_factor_in_hint NAME_OB ')'
{
malloc_non_terminal_node($$, result->malloc_pool_, T_INDEX_SS_ASC_HINT, 3, $3, $4, $5);
}
| INDEX_SS_DESC_HINT '(' qb_name_option relation_factor_in_hint NAME_OB ')'
{
malloc_non_terminal_node($$, result->malloc_pool_, T_INDEX_SS_DESC_HINT, 3, $3, $4, $5);
}
| LEADING_HINT '(' qb_name_option relation_factor_in_leading_hint_list ')'
{
malloc_non_terminal_node($$, result->malloc_pool_, T_LEADING, 2, $3, $4);

5
src/sql/resolver/dml/ob_dml_resolver.cpp Normal file → Executable file
View File

@ -9485,7 +9485,10 @@ int ObDMLResolver::resolve_optimize_hint(const ParseNode &hint_node,
case T_NO_INDEX_HINT:
case T_FULL_HINT:
case T_USE_DAS_HINT:
case T_NO_USE_DAS_HINT: {
case T_NO_USE_DAS_HINT:
case T_INDEX_SS_HINT:
case T_INDEX_SS_ASC_HINT:
case T_INDEX_SS_DESC_HINT: {
if (OB_FAIL(resolve_index_hint(hint_node, opt_hint))) {
LOG_WARN("failed to resolve index hint", K(ret));
}

3
src/sql/resolver/dml/ob_hint.cpp Normal file → Executable file
View File

@ -780,6 +780,9 @@ const char* ObHint::get_hint_name(ObItemType type, bool is_enable_hint /* defaul
case T_FULL_HINT: return "FULL";
case T_NO_INDEX_HINT: return "NO_INDEX";
case T_USE_DAS_HINT: return is_enable_hint ? "USE_DAS" : "NO_USE_DAS";
case T_INDEX_SS_HINT: return "INDEX_SS";
case T_INDEX_SS_ASC_HINT: return "INDEX_SS_ASC";
case T_INDEX_SS_DESC_HINT: return "INDEX_SS_DESC";
case T_LEADING: return is_enable_hint ? "LEADING" : "ORDERED";
case T_USE_MERGE: return is_enable_hint ? "USE_MERGE" : "NO_USE_MERGE";
case T_USE_HASH: return is_enable_hint ? "USE_HASH" : "NO_USE_HASH";

View File

@ -700,6 +700,9 @@ public:
const ObTableInHint &get_table() const { return table_; }
ObString &get_index_name() { return index_name_; }
const ObString &get_index_name() const { return index_name_; }
bool is_use_index_hint() const { return T_NO_INDEX_HINT != get_hint_type(); }
bool use_skip_scan() const { return T_INDEX_SS_HINT == get_hint_type(); }
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(table), K_(index_name));
private:

View File

@ -1171,7 +1171,10 @@ int ObStmtHint::merge_other_opt_hint(const ObIArray<ObHint*> &hints,
switch (hint->get_hint_type()) {
case T_INDEX_HINT:
case T_NO_INDEX_HINT:
case T_FULL_HINT: {
case T_FULL_HINT:
case T_INDEX_SS_HINT:
case T_INDEX_SS_ASC_HINT:
case T_INDEX_SS_DESC_HINT: {
hint_type = T_INDEX_HINT;
break;
}
@ -1797,6 +1800,34 @@ int ObLogPlanHint::check_use_das(uint64_t table_id, bool &force_das, bool &force
return ret;
}
int ObLogPlanHint::check_use_skip_scan(uint64_t table_id,
uint64_t index_id,
bool &force_skip_scan,
bool &force_no_skip_scan) const
{
int ret = OB_SUCCESS;
force_skip_scan = false;
force_no_skip_scan = false;
const LogTableHint *log_table_hint = get_log_table_hint(table_id);
int64_t pos = OB_INVALID_INDEX;
if (NULL != log_table_hint &&
ObOptimizerUtil::find_item(log_table_hint->index_list_, index_id, &pos)) {
const ObIndexHint *hint = NULL;
if (OB_UNLIKELY(pos >= log_table_hint->index_hints_.count() || pos < 0)
|| OB_ISNULL(hint = log_table_hint->index_hints_.at(pos))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected pos", K(ret), K(pos), K(log_table_hint->index_hints_.count()), K(hint));
} else {
force_skip_scan = hint->use_skip_scan();
force_no_skip_scan = !force_skip_scan && hint->is_use_index_hint();
}
}
if (OB_SUCC(ret) && !force_skip_scan && !force_no_skip_scan && is_outline_data_) {
force_no_skip_scan = true;
}
return ret;
}
int ObLogPlanHint::check_use_join_filter(uint64_t filter_table_id,
const ObRelIds &left_tables,
bool part_join_filter,
@ -2183,7 +2214,6 @@ int LogTableHint::assign(const LogTableHint &other)
{
int ret = OB_SUCCESS;
table_ = other.table_;
index_type_ = other.index_type_;
parallel_hint_ = other.parallel_hint_;
use_das_hint_ = other.use_das_hint_;
if (OB_FAIL(index_list_.assign(other.index_list_))) {
@ -2223,9 +2253,10 @@ int LogTableHint::init_index_hints(ObSqlSchemaGuard &schema_guard)
} else {
LOG_TRACE("get readable index", K(table_index_count));
const share::schema::ObTableSchema *index_schema = NULL;
ObItemType index_hint_type = T_INVALID;
ObSEArray<uint64_t, 4> index_list;
ObSEArray<const ObIndexHint*, 4> hints;
ObSEArray<uint64_t, 4> no_index_list;
ObSEArray<const ObIndexHint*, 4> index_hints;
ObSEArray<const ObIndexHint*, 4> no_index_hints;
for (int64_t i = -1; OB_SUCC(ret) && i < table_index_count; ++i) {
uint64_t index_id = -1 == i ? table_->ref_id_ : tids[i];
ObString index_name;
@ -2244,54 +2275,63 @@ int LogTableHint::init_index_hints(ObSqlSchemaGuard &schema_guard)
}
if (OB_SUCC(ret) && (!index_name.empty())) {
int64_t hint_pos = OB_INVALID_INDEX;
int64_t no_index_hint_pos = OB_INVALID_INDEX;
int64_t index_hint_pos = OB_INVALID_INDEX;
int64_t index_ss_hint_pos = OB_INVALID_INDEX;
const uint64_t N = index_hints_.count();
const ObIndexHint *index_hint = NULL;
bool use_index = false;
bool no_use_index = false;
for (int64_t hint_i = 0; OB_SUCC(ret) && hint_i < N; ++hint_i) {
if (OB_ISNULL(index_hint = index_hints_.at(hint_i)) ||
OB_UNLIKELY(!index_hint->is_access_path_hint())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null index hint", K(ret), K(index_hint));
} else if ((is_primary_key && T_FULL_HINT == index_hint->get_hint_type())
|| 0 == index_hint->get_index_name().case_compare(index_name)) {
hint_pos = hint_i;
use_index |= T_INDEX_HINT == index_hint->get_hint_type()
|| T_FULL_HINT == index_hint->get_hint_type();
no_use_index |= T_NO_INDEX_HINT == index_hint->get_hint_type();
} else if (is_primary_key && T_FULL_HINT == index_hint->get_hint_type()) {
index_hint_pos = hint_i;
} else if (0 != index_hint->get_index_name().case_compare(index_name)) {
/* do nothing */
} else if (T_NO_INDEX_HINT == index_hint->get_hint_type()) {
no_index_hint_pos = hint_i;
} else if (T_INDEX_SS_HINT == index_hint->get_hint_type()) {
index_ss_hint_pos = hint_i;
} else {
index_hint_pos = hint_i;
}
}
if (hint_pos >= 0 && hint_pos < N) {
if (use_index && no_use_index) {
/* conflict full/index and no_index hint*/
} else if (no_use_index && T_INDEX_HINT == index_hint_type) {
/* get vaild index hint, ignore this no_index hint*/
} else {
if (use_index && T_NO_INDEX_HINT == index_hint_type) {
hints.reuse();
index_list.reuse();
}
index_hint_type = use_index ? T_INDEX_HINT : T_NO_INDEX_HINT;
if (OB_FAIL(index_list.push_back(index_id))) {
LOG_WARN("fail to push back", K(ret), K(index_id));
} else if (OB_FAIL(hints.push_back(index_hints_.at(hint_pos)))) {
LOG_WARN("fail to push back", K(ret), K(hint_pos));
}
if (OB_FAIL(ret)) {
} else if (OB_INVALID_INDEX != no_index_hint_pos
&& (OB_INVALID_INDEX != index_ss_hint_pos
|| OB_INVALID_INDEX != index_hint_pos)) {
/* conflict full/index/index_ss and no_index hint*/
} else if (OB_INVALID_INDEX != no_index_hint_pos) {
if (OB_FAIL(no_index_list.push_back(index_id))) {
LOG_WARN("fail to push back", K(ret), K(index_id));
} else if (OB_FAIL(no_index_hints.push_back(index_hints_.at(no_index_hint_pos)))) {
LOG_WARN("fail to push back", K(ret), K(no_index_hint_pos));
}
} else if (OB_INVALID_INDEX != index_ss_hint_pos
|| OB_INVALID_INDEX != index_hint_pos) {
int64_t hint_pos = OB_INVALID_INDEX != index_ss_hint_pos
? index_ss_hint_pos : index_hint_pos;
if (OB_FAIL(index_list.push_back(index_id))) {
LOG_WARN("fail to push back", K(ret), K(index_id));
} else if (OB_FAIL(index_hints.push_back(index_hints_.at(hint_pos)))) {
LOG_WARN("fail to push back", K(ret), K(hint_pos));
}
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(index_list.count() != hints.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected log index hint", K(ret), K(index_list), K(hints));
} else if (OB_FAIL(index_list_.assign(index_list))) {
LOG_WARN("failed to assign array", K(ret));
} else if (OB_FAIL(index_hints_.assign(hints))) {
LOG_WARN("failed to assign array", K(ret));
} else {
index_type_ = index_hint_type;
if (OB_SUCC(ret)) {
if (!index_list.empty()) {
if (OB_FAIL(index_list_.assign(index_list))) {
LOG_WARN("failed to assign array", K(ret));
} else if (OB_FAIL(index_hints_.assign(index_hints))) {
LOG_WARN("failed to assign array", K(ret));
}
} else if (OB_FAIL(index_list_.assign(no_index_list))) {
LOG_WARN("failed to assign array", K(ret));
} else if (OB_FAIL(index_hints_.assign(no_index_hints))) {
LOG_WARN("failed to assign array", K(ret));
}
}
}
return ret;
@ -2367,5 +2407,31 @@ int LogTableHint::add_join_filter_hint(const ObDMLStmt &stmt,
return ret;
}
int LogTableHint::allowed_skip_scan(const uint64_t index_id, bool &allowed) const
{
int ret = OB_SUCCESS;
allowed = false;
if (!is_use_index_hint()) {
/* do nothing */
} else if (OB_UNLIKELY(index_list_.count() != index_hints_.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected count", K(ret), K(index_list_.count()), K(index_hints_.count()));
} else {
bool find = false;
for (int64_t i = 0; OB_SUCC(ret) && !find && i < index_list_.count(); ++i) {
if (index_list_.at(i) != index_id) {
/* do nothing */
} else if (OB_ISNULL(index_hints_.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(i), K(index_hints_));
} else {
allowed = T_INDEX_SS_HINT == index_hints_.at(i)->get_hint_type();
find = true;
}
}
}
return ret;
}
}//end of namespace sql
}//end of namespace oceanbase

14
src/sql/resolver/dml/ob_sql_hint.h Normal file → Executable file
View File

@ -280,17 +280,15 @@ struct LogJoinHint
struct LogTableHint
{
LogTableHint() : table_(NULL),
index_type_(T_INVALID),
parallel_hint_(NULL),
use_das_hint_(NULL) {}
LogTableHint(const TableItem *table) : table_(table),
index_type_(T_INVALID),
parallel_hint_(NULL),
use_das_hint_(NULL) {}
int assign(const LogTableHint &other);
int init_index_hints(ObSqlSchemaGuard &schema_guard);
bool is_no_index_hint() const { return T_NO_INDEX_HINT == index_type_; }
bool is_index_hint() const { return T_INDEX_HINT == index_type_; }
bool is_use_index_hint() const { return !index_hints_.empty() && NULL != index_hints_.at(0)
&& index_hints_.at(0)->is_use_index_hint(); }
bool is_valid() const { return !index_list_.empty() || NULL != parallel_hint_
|| NULL != use_das_hint_ || !join_filter_hints_.empty(); }
int get_join_filter_hint(const ObRelIds &left_tables,
@ -299,14 +297,13 @@ struct LogTableHint
int add_join_filter_hint(const ObDMLStmt &stmt,
const ObQueryHint &query_hint,
const ObJoinFilterHint &hint);
int allowed_skip_scan(const uint64_t index_id, bool &allowed) const;
TO_STRING_KV(K_(table), K_(index_type),
K_(index_list), K_(index_hints),
TO_STRING_KV(K_(table), K_(index_list), K_(index_hints),
K_(parallel_hint), K_(use_das_hint),
K_(join_filter_hints), K_(left_tables));
const TableItem *table_;
ObItemType index_type_;
common::ObSEArray<uint64_t, 4, common::ModulePageAllocator, true> index_list_;
common::ObSEArray<const ObIndexHint*, 4, common::ModulePageAllocator, true> index_hints_;
const ObTableParallelHint *parallel_hint_;
@ -397,6 +394,9 @@ struct ObLogPlanHint
bool &can_use,
const ObJoinFilterHint *&force_hint) const;
int check_use_das(uint64_t table_id, bool &force_das, bool &force_no_das) const;
int check_use_skip_scan(uint64_t table_id, uint64_t index_id,
bool &force_skip_scan,
bool &force_no_skip_scan) const;
const LogJoinHint* get_join_hint(const ObRelIds &join_tables) const;
const ObIArray<LogJoinHint> &get_join_hints() const { return join_hints_; }
SetAlgo get_valid_set_algo() const;

View File

@ -73,6 +73,7 @@ ObQueryRange::ObQueryRange()
query_range_ctx_(NULL),
key_part_store_(allocator_),
range_exprs_(allocator_),
ss_range_exprs_(allocator_),
mbr_filters_(allocator_),
has_exec_param_(true),
is_equal_and_(false),
@ -93,6 +94,7 @@ ObQueryRange::ObQueryRange(ObIAllocator &alloc)
query_range_ctx_(NULL),
key_part_store_(allocator_),
range_exprs_(allocator_),
ss_range_exprs_(allocator_),
mbr_filters_(allocator_),
has_exec_param_(true),
is_equal_and_(false),
@ -131,6 +133,7 @@ void ObQueryRange::reset()
contain_geo_filters_ = false;
table_graph_.reset();
range_exprs_.reset();
ss_range_exprs_.reset();
inner_allocator_.reset();
has_exec_param_ = true;
is_equal_and_ = false;
@ -290,17 +293,10 @@ int ObQueryRange::preliminary_extract_query_range(const ColumnIArray &range_colu
if (OB_SUCC(ret) && NULL != root) {
if (OB_FAIL(refine_large_range_graph(root))) {
LOG_WARN("failed to refine large range graph", K(ret));
} else if (OB_FAIL(remove_useless_range_graph(root))) {
LOG_WARN("failed to remove useless range", K(ret));
} else if (OB_FAIL(check_graph_type(*root))) {
LOG_WARN("check graph type failed", K(ret));
} else if (OB_FAIL(generate_expr_final_info())) {
LOG_WARN("failed to generate final exprs");
} else {
SQL_REWRITE_LOG(DEBUG, "root key part", K(*root));
int64_t max_pos = -1;
table_graph_.key_part_head_ = root;
table_graph_.is_standard_range_ = is_standard_graph(root);
OZ(is_strict_equal_graph(root, 0, max_pos, table_graph_.is_equal_range_));
OZ(check_graph_type());
LOG_WARN("failed to generate final exprs");
}
}
}
@ -418,24 +414,13 @@ int ObQueryRange::preliminary_extract_query_range(const ColumnIArray &range_colu
// no range left
} else if (OB_FAIL(refine_large_range_graph(temp_result))) {
LOG_WARN("failed to refine large range graph", K(ret));
} else if (OB_FAIL(remove_useless_range_graph(temp_result))) {
LOG_WARN("failed to remove useless range", K(ret));
} else if (OB_FAIL(check_graph_type(*temp_result))) {
LOG_WARN("check graph type failed", K(ret));
} else if (OB_FAIL(generate_expr_final_info())) {
LOG_WARN("failed to generate final exprs");
} else {
int64_t max_pos = -1;
table_graph_.key_part_head_ = temp_result;
table_graph_.is_standard_range_ = is_standard_graph(temp_result);
if (OB_FAIL(is_strict_equal_graph(temp_result,
0,
max_pos,
table_graph_.is_equal_range_))) {
LOG_WARN("is strict equal graph failed", K(ret));
} else if (OB_FAIL(check_graph_type())) {
LOG_WARN("check graph type failed", K(ret));
}
}
}
if (OB_SUCC(ret)) {
if (query_range_ctx_->need_final_extact_) {
state_ = NEED_PREPARE_PARAMS;
@ -715,63 +700,172 @@ int ObQueryRange::check_is_get(ObKeyPart &key_part,
return ret;
}
int ObQueryRange::check_graph_type()
// 1. check range graph type: is_standard_range_/is_equal_range_/is_precise_get_/is_skip_scan_
// 3. remove useless key part
int ObQueryRange::check_graph_type(ObKeyPart &key_part_head)
{
int ret = OB_SUCCESS;
table_graph_.is_precise_get_ = true;
if (OB_ISNULL(query_range_ctx_) || OB_ISNULL(table_graph_.key_part_head_)) {
ret = OB_NOT_INIT;
LOG_WARN("query isn't init", K_(query_range_ctx), K_(table_graph_.key_part_head));
int64_t max_pos = -1;
int64_t max_precise_pos = -1;
int64_t ss_max_precise_pos = -1;
table_graph_.key_part_head_ = &key_part_head;
table_graph_.is_standard_range_ = is_standard_graph(&key_part_head);
table_graph_.is_precise_get_ = is_precise_get(key_part_head, max_precise_pos);
table_graph_.skip_scan_offset_ = -1;
ObKeyPart *ss_head = NULL;
if (OB_FAIL(check_skip_scan_range(&key_part_head,
table_graph_.is_standard_range_,
max_precise_pos,
ss_head,
table_graph_.skip_scan_offset_,
ss_max_precise_pos))) {
LOG_WARN("failed to check skip scan", K(ret));
} else if (OB_FAIL(is_strict_equal_graph(&key_part_head, 0, max_pos, table_graph_.is_equal_range_))) {
LOG_WARN("is strict equal graph failed", K(ret));
} else if (OB_FAIL(remove_useless_range_graph(is_ss_range() ? ss_head : &key_part_head))) {
LOG_WARN("failed to remove useless range", K(ret));
} else if (OB_FAIL(remove_precise_range_expr(is_ss_range() ? ss_max_precise_pos : max_precise_pos))) {
LOG_WARN("remove precise range expr failed", K(ret));
} else if (OB_FAIL(fill_range_exprs(max_precise_pos, table_graph_.skip_scan_offset_, ss_max_precise_pos))) {
LOG_WARN("failed to fill range exprs", K(ret));
}
if (OB_SUCC(ret)) {
int64_t max_pos = -1;
int64_t depth = -1;
int64_t column_count = column_count_;
bool is_terminated = false;
for (ObKeyPart *cur = table_graph_.key_part_head_; !is_terminated && NULL != cur; cur = cur->and_next_) {
if (cur->pos_.offset_ != (++depth)) {
table_graph_.is_precise_get_ = false;
max_pos = depth;
is_terminated = true;
} else if (NULL != cur->or_next_ || NULL != cur->item_next_) {
table_graph_.is_precise_get_ = false;
} else if (cur->is_like_key() || cur->is_geo_key()) {
table_graph_.is_precise_get_ = false;
} else if (!cur->is_equal_condition()) {
table_graph_.is_precise_get_ = false;
} else {
return ret;
}
int ObQueryRange::check_skip_scan_range(ObKeyPart *key_part_head,
const bool is_standard_range,
const int64_t max_precise_pos,
ObKeyPart *&ss_head,
int64_t &skip_scan_offset,
int64_t &ss_max_precise_pos)
{
int ret = OB_SUCCESS;
ss_head = NULL;
skip_scan_offset = -1;
ss_max_precise_pos = -1;
if (!is_standard_range) {
/* only standard range can extract skip scan range */
} else {
ObKeyPart *cur = key_part_head;
// skip prefix precise range
while (NULL != cur && cur->pos_.offset_ < max_precise_pos) {
cur = cur->and_next_;
}
if (NULL != cur) {
ss_head = cur;
skip_scan_offset = ss_head->pos_.offset_;
is_precise_get(*ss_head, ss_max_precise_pos, true);
}
}
return ret;
}
int ObQueryRange::reset_skip_scan_range()
{
int ret = OB_SUCCESS;
if (-1 == table_graph_.skip_scan_offset_) {
/* do nothing */
} else if (OB_ISNULL(table_graph_.key_part_head_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(table_graph_.key_part_head_));
} else {
int64_t max_precise_pos = -1;
table_graph_.is_precise_get_ = is_precise_get(*table_graph_.key_part_head_, max_precise_pos);
table_graph_.skip_scan_offset_ = -1;
ss_range_exprs_.reset();
if (OB_FAIL(remove_useless_range_graph(table_graph_.key_part_head_))) {
LOG_WARN("failed to remove useless range", K(ret));
} else if (OB_FAIL(remove_precise_range_expr(max_precise_pos))) {
LOG_WARN("remove precise range expr failed", K(ret));
}
}
return ret;
}
bool ObQueryRange::is_precise_get(const ObKeyPart &key_part_head,
int64_t &max_precise_pos,
bool ignore_head /* = false */)
{
bool is_precise_get = true;
int64_t max_pos = -1;
int64_t depth = ignore_head ? key_part_head.pos_.offset_ - 1 : -1;
bool is_terminated = false;
for (const ObKeyPart *cur = &key_part_head; !is_terminated && NULL != cur; cur = cur->and_next_) {
if (cur->pos_.offset_ != (++depth)) {
is_precise_get = false;
max_pos = depth;
is_terminated = true;
} else if (NULL != cur->or_next_ || NULL != cur->item_next_) {
is_precise_get = false;
} else if (cur->is_like_key() || cur->is_geo_key()) {
is_precise_get = false;
} else if (!cur->is_equal_condition()) {
is_precise_get = false;
} else {
// do nothing
}
if (!is_terminated) {
if (is_strict_in_graph(cur)) {
// do nothing
} else if (!is_general_graph(*cur)) {
max_pos = cur->pos_.offset_ + 1;
is_terminated = true;
} else if (has_scan_key(*cur)) {
max_pos = cur->pos_.offset_ + 1;
is_terminated = true;
}
if (OB_SUCC(ret) && !is_terminated) {
if (is_strict_in_graph(cur)) {
// do nothing
} else if (!is_general_graph(*cur)) {
max_pos = cur->pos_.offset_ + 1;
is_terminated = true;
} else if (has_scan_key(*cur)) {
max_pos = cur->pos_.offset_ + 1;
is_terminated = true;
}
}
max_precise_pos = is_terminated ? max_pos : depth + 1;
if (is_precise_get && depth != column_count_ - 1) {
is_precise_get = false;
}
return is_precise_get;
}
int ObQueryRange::fill_range_exprs(const int64_t max_precise_pos,
const int64_t ss_offset,
const int64_t ss_max_precise_pos)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(query_range_ctx_)) {
ret = OB_NOT_INIT;
LOG_WARN("query isn't init", K_(query_range_ctx));
} else {
ObSEArray<ObRawExpr*, 4> range_exprs;
ObSEArray<ObRawExpr*, 4> ss_range_exprs;
bool precise = true;
bool ss_precise = true;
for (int64_t i = 0; OB_SUCC(ret) && i < query_range_ctx_->precise_range_exprs_.count(); ++i) {
precise = true;
ss_precise = is_ss_range();
ObRangeExprItem &expr_item = query_range_ctx_->precise_range_exprs_.at(i);
for (int64_t j = 0 ; (precise || ss_precise) && j < expr_item.cur_pos_.count() ; ++j) {
if (expr_item.cur_pos_.at(j) >= max_precise_pos) {
precise = false;
}
if (ss_precise && (expr_item.cur_pos_.at(j) < ss_offset || expr_item.cur_pos_.at(j) >= ss_max_precise_pos)) {
ss_precise = false;
}
}
if (OB_SUCC(ret) && NULL != expr_item.cur_expr_) {
if (precise && OB_FAIL(range_exprs.push_back(const_cast<ObRawExpr*>(expr_item.cur_expr_)))) {
LOG_WARN("push back precise range expr failed", K(ret));
} else if (ss_precise && OB_FAIL(ss_range_exprs.push_back(const_cast<ObRawExpr*>(expr_item.cur_expr_)))) {
LOG_WARN("push back precise range expr failed", K(ret));
}
}
}
if (OB_SUCC(ret)) {
max_pos = is_terminated ? max_pos : depth + 1;
if (OB_FAIL(remove_precise_range_expr(max_pos))) {
LOG_WARN("remove precise range expr failed", K(ret));
} else if (table_graph_.is_precise_get_ && depth != column_count - 1) {
table_graph_.is_precise_get_ = false;
}
}
}
if (OB_SUCC(ret) && OB_FAIL(range_exprs_.init(query_range_ctx_->precise_range_exprs_.count()))) {
LOG_WARN("init range exprs failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < query_range_ctx_->precise_range_exprs_.count(); ++i) {
const ObRawExpr *cur_expr = query_range_ctx_->precise_range_exprs_.at(i).cur_expr_;
if (NULL != cur_expr) {
if (OB_FAIL(range_exprs_.push_back(const_cast<ObRawExpr*>(cur_expr)))) {
LOG_WARN("push back precise range expr failed", K(ret));
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(range_exprs_.assign(range_exprs))) {
LOG_WARN("failed to assign range exprs", K(ret));
} else if (OB_FAIL(ss_range_exprs_.assign(ss_range_exprs))) {
LOG_WARN("failed to assign skip scan range exprs", K(ret));
} else {
LOG_DEBUG("finish fill range exprs", K(max_precise_pos), K(range_exprs));
LOG_DEBUG("finish fill skip scan range exprs", K(ss_offset), K(ss_max_precise_pos), K(ss_range_exprs));
}
}
return ret;
@ -4737,6 +4831,31 @@ int ObQueryRange::get_tablet_ranges(common::ObIAllocator &allocator,
return ret;
}
int ObQueryRange::get_ss_tablet_ranges(common::ObIAllocator &allocator,
ObExecContext &exec_ctx,
ObQueryRangeArray &ss_ranges,
const ObDataTypeCastParams &dtc_params) const
{
int ret = OB_SUCCESS;
ss_ranges.reuse();
const ObKeyPart *ss_head = get_ss_key_part_head();
if (NULL == ss_head) {
/* is not skip scan range */
} else if (OB_UNLIKELY(table_graph_.skip_scan_offset_ < 0
|| table_graph_.skip_scan_offset_ >= column_count_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected skip scan range", K(ret), K(table_graph_.skip_scan_offset_),
K(column_count_));
} else if (OB_FAIL(gen_skip_scan_range(allocator, exec_ctx, dtc_params, ss_head,
column_count_ - table_graph_.skip_scan_offset_,
ss_ranges))) {
LOG_WARN("get skip scan ranges failed", K(ret));
} else {
LOG_DEBUG("get skip range success", K(ss_ranges));
}
return ret;
}
int ObQueryRange::ObSearchState::tailor_final_range(int64_t column_count)
{
int ret = OB_SUCCESS;
@ -4781,6 +4900,54 @@ int ObQueryRange::ObSearchState::tailor_final_range(int64_t column_count)
return ret;
}
int ObQueryRange::ObSearchState::init_search_state(int64_t column_count, bool init_as_full_range)
{
int ret = OB_SUCCESS;
void *start_ptr = NULL;
void *end_ptr = NULL;
if (OB_UNLIKELY(column_count <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected column count when init search state", K(ret), K(column_count));
} else if (OB_ISNULL(start_ptr = allocator_.alloc(sizeof(ObObj) * column_count))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for start_ptr failed", K(ret));
} else if(OB_ISNULL(end_ptr = allocator_.alloc(sizeof(ObObj) * column_count))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for end_ptr failed", K(ret));
} else if (OB_ISNULL(include_start_ = static_cast<bool*>(allocator_.alloc(sizeof(bool) * column_count)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for search state start failed", K(ret));
} else if (OB_ISNULL(include_end_ = static_cast<bool*>(allocator_.alloc(sizeof(bool) * column_count)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for search state end failed", K(ret));
} else {
start_ = new(start_ptr) ObObj[column_count];
end_ = new(end_ptr) ObObj[column_count];
if (init_as_full_range) {
max_exist_index_ = column_count;
last_include_start_ = true;
last_include_end_ = true;
for (int64_t i = 0; i < column_count; ++i) {
start_[i].set_min_value();
end_[i].set_max_value();
include_start_[i] = false;
include_end_[i] = false;
}
} else {
max_exist_index_ = 0;
last_include_start_ = false;
last_include_end_ = false;
for (int64_t i = 0; i < column_count; ++i) {
start_[i].set_min_value();
end_[i].set_max_value();
include_start_[i] = false;
include_end_[i] = false;
}
}
}
return ret;
}
// @notice 调用这个接口之前必须调用need_deep_copy()来判断是否可以不用拷贝就进行final extract
int ObQueryRange::get_tablet_ranges(ObIAllocator &allocator,
ObExecContext &exec_ctx,
@ -4814,6 +4981,60 @@ int ObQueryRange::get_tablet_ranges(ObIAllocator &allocator,
return ret;
}
// for standard range, check is skip scan range
const ObKeyPart *ObQueryRange::get_ss_key_part_head() const
{
const ObKeyPart *ss_head = NULL;
if (is_ss_range()) {
const ObKeyPart *cur = table_graph_.key_part_head_;
while (NULL != cur && cur->pos_.offset_ < table_graph_.skip_scan_offset_) {
cur = cur->and_next_;
}
if (NULL != cur && cur->pos_.offset_ == table_graph_.skip_scan_offset_) {
ss_head = cur;
}
}
return ss_head;
}
OB_NOINLINE int ObQueryRange::gen_skip_scan_range(ObIAllocator &allocator,
ObExecContext &exec_ctx,
const ObDataTypeCastParams &dtc_params,
const ObKeyPart *ss_root,
int64_t post_column_count,
ObQueryRangeArray &ss_ranges) const
{
int ret = OB_SUCCESS;
bool is_get_range = false;
ObSearchState search_state(allocator);
ObNewRange *ss_range = NULL;
if (OB_ISNULL(ss_root) || OB_UNLIKELY(1 > post_column_count)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected skip scan range", K(ret), K(ss_root), K(post_column_count));
} else if (OB_FAIL(search_state.init_search_state(post_column_count, true))) {
LOG_WARN("failed to init postfix search state", K(ret));
}
for (const ObKeyPart *cur = ss_root; OB_SUCC(ret) && NULL != cur && !search_state.is_empty_range_;
cur = cur->and_next_) {
if (OB_FAIL(get_single_key_value(cur, exec_ctx, search_state, dtc_params,
table_graph_.skip_scan_offset_))) {
LOG_WARN("get single key value failed", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if(OB_FAIL(search_state.tailor_final_range(post_column_count))) {
LOG_WARN("tailor final range failed", K(ret));
} else if (OB_FAIL(generate_single_range(search_state, post_column_count,
table_graph_.key_part_head_->id_.table_id_,
ss_range, is_get_range))) {
LOG_WARN("generate single range failed", K(ret));
} else if (OB_FAIL(ss_ranges.push_back(ss_range))) {
LOG_WARN("push back range to array failed", K(ret));
}
return ret;
}
OB_NOINLINE int ObQueryRange::gen_simple_scan_range(ObIAllocator &allocator,
ObExecContext &exec_ctx,
ObQueryRangeArray &ranges,
@ -4822,34 +5043,8 @@ OB_NOINLINE int ObQueryRange::gen_simple_scan_range(ObIAllocator &allocator,
{
int ret = OB_SUCCESS;
ObSearchState search_state(allocator);
void *start_ptr = NULL;
void *end_ptr = NULL;
if (OB_ISNULL(start_ptr = search_state.allocator_.alloc(sizeof(ObObj) * column_count_))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for start_ptr failed", K(ret));
} else if(OB_ISNULL(end_ptr = search_state.allocator_.alloc(sizeof(ObObj) * column_count_))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for end_ptr failed", K(ret));
} else if (OB_ISNULL(search_state.include_start_ = static_cast<bool*>(search_state.allocator_.alloc(sizeof(bool) * column_count_)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for search state start failed", K(ret));
} else if (OB_ISNULL(search_state.include_end_ = static_cast<bool*>(search_state.allocator_.alloc(sizeof(bool) * column_count_)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory for search state end failed", K(ret));
} else {
search_state.start_ = new(start_ptr) ObObj[column_count_];
search_state.end_ = new(end_ptr) ObObj[column_count_];
search_state.max_exist_index_ = column_count_;
search_state.last_include_start_ = true;
search_state.last_include_end_ = true;
}
for (int64_t i = 0; OB_SUCC(ret) && i < column_count_; ++i) {
//将所有range都初始化成true
search_state.start_[i].set_min_value();
search_state.end_[i].set_max_value();
search_state.include_start_[i] = false;
search_state.include_end_[i] = false;
if (OB_FAIL(search_state.init_search_state(column_count_, true))) {
LOG_WARN("failed to init search state", K(ret));
}
for (ObKeyPart *cur = table_graph_.key_part_head_;
OB_SUCC(ret) && NULL != cur && !search_state.is_empty_range_;
@ -4943,7 +5138,8 @@ if (OB_SUCC(ret) ) { \
inline int ObQueryRange::get_single_key_value(const ObKeyPart *key,
ObExecContext &exec_ctx,
ObSearchState &search_state,
const ObDataTypeCastParams &dtc_params) const
const ObDataTypeCastParams &dtc_params,
int64_t skip_offset /* default 0 */ ) const
{
int ret = OB_SUCCESS;
for (const ObKeyPart *cur = key;
@ -5028,7 +5224,7 @@ inline int ObQueryRange::get_single_key_value(const ObKeyPart *key,
CAST_VALUE_TYPE(expect_type, cur->pos_.column_type_, start, include_start, end, include_end);
}
if (OB_SUCC(ret)) {
search_state.depth_ = static_cast<int>(cur->pos_.offset_);
search_state.depth_ = static_cast<int>(cur->pos_.offset_ - skip_offset);
if (search_state.is_phy_rowid_range_ != cur->is_phy_rowid_key_part()) {
if (search_state.is_phy_rowid_range_) {
//do nothing
@ -5078,36 +5274,15 @@ OB_NOINLINE int ObQueryRange::get_tablet_ranges(ObQueryRangeArray &ranges,
} else if (OB_FAIL(get_methods.push_back(is_get_range))) {
LOG_WARN("push back get_method failed", K(ret));
} else {}
} else if (OB_FAIL(search_state.init_search_state(column_count_, false))) {
LOG_WARN("failed to init search state", K(ret));
} else {
ret = OB_SUCCESS;
search_state.depth_ = 0;
search_state.max_exist_index_ = 0;
search_state.last_include_start_ = false;
search_state.last_include_end_ = false;
search_state.produce_range_ = true;
search_state.is_equal_range_ = table_graph_.is_equal_range_;
search_state.start_ = static_cast<ObObj *>(search_state.allocator_.alloc(sizeof(ObObj) * column_count_));
search_state.end_ = static_cast<ObObj *>(search_state.allocator_.alloc(sizeof(ObObj) * column_count_));
search_state.include_start_ = static_cast<bool*>(search_state.allocator_.alloc(sizeof(bool) * column_count_));
search_state.include_end_ = static_cast<bool*>(search_state.allocator_.alloc(sizeof(bool) * column_count_));
if (OB_ISNULL(search_state.start_) || OB_ISNULL(search_state.end_)
|| OB_ISNULL(search_state.include_start_) || OB_ISNULL(search_state.include_end_)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(search_state.start_), K(search_state.end_),
K_(search_state.include_start), K_(search_state.include_end), K_(column_count));
} else {
for (int i = 0; i < column_count_; ++i) {
new(search_state.start_ + i) ObObj();
new(search_state.end_ + i) ObObj();
(search_state.start_ + i)->set_max_value();
(search_state.end_ + i)->set_min_value();
search_state.include_start_[i] = false;
search_state.include_end_[i] = false;
}
if (OB_FAIL(and_first_search(search_state, table_graph_.key_part_head_, ranges,
get_methods, dtc_params))) {
LOG_WARN("and_first_search failed", K(ret));
}
if (OB_FAIL(and_first_search(search_state, table_graph_.key_part_head_, ranges,
get_methods, dtc_params))) {
LOG_WARN("and_first_search failed", K(ret));
}
}
if (OB_SUCC(ret)) {
@ -5873,6 +6048,7 @@ OB_DEF_SERIALIZE(ObQueryRange)
LOG_WARN("serialize srid map failed", K(ret));
}
}
OB_UNIS_ENCODE(table_graph_.skip_scan_offset_);
return ret;
}
@ -5907,6 +6083,7 @@ OB_DEF_SERIALIZE_SIZE(ObQueryRange)
if (map_count > 0) {
len += get_columnId_map_size();
}
OB_UNIS_ADD_LEN(table_graph_.skip_scan_offset_);
return len;
}
@ -5949,6 +6126,7 @@ OB_DEF_DESERIALIZE(ObQueryRange)
LOG_WARN("deserialize range graph failed", K(ret));
}
}
OB_UNIS_DECODE(table_graph_.skip_scan_offset_);
return ret;
}
@ -6059,9 +6237,10 @@ OB_NOINLINE int ObQueryRange::deep_copy(const ObQueryRange &other,
contain_geo_filters_ = other.contain_geo_filters_;
has_exec_param_ = other.has_exec_param_;
is_equal_and_ = other.is_equal_and_;
if (OB_FAIL(range_exprs_.assign(other.range_exprs_))) {
LOG_WARN("assign range exprs failed", K(ret));
} else if (OB_FAIL(ss_range_exprs_.assign(other.ss_range_exprs_))) {
LOG_WARN("assign range exprs failed", K(ret));
} else if (OB_FAIL(table_graph_.assign(other_graph))) {
LOG_WARN("Deep copy range columns failed", K(ret));
} else if (OB_FAIL(equal_offs_.assign(other.equal_offs_))) {

View File

@ -239,6 +239,7 @@ private:
{
}
int init_search_state(int64_t column_count, bool init_as_full_range);
bool has_intersect(const common::ObObj &start,
bool include_start,
const common::ObObj &end,
@ -293,7 +294,8 @@ private:
: key_part_head_(NULL),
is_equal_range_(false),
is_standard_range_(true),
is_precise_get_(false)
is_precise_get_(false),
skip_scan_offset_(-1)
{
//将is_standard_range_初始化为true的原因是我们认为当表达式条件为空的时候也是一个简单range
}
@ -304,6 +306,7 @@ private:
is_equal_range_ = false;
is_standard_range_ = true;
is_precise_get_ = false;
skip_scan_offset_ = -1;
}
int assign(const ObRangeGraph &other)
@ -313,6 +316,7 @@ private:
is_equal_range_ = other.is_equal_range_;
is_standard_range_ = other.is_standard_range_;
is_precise_get_ = other.is_precise_get_;
skip_scan_offset_ = other.skip_scan_offset_;
return ret;
}
@ -320,6 +324,7 @@ private:
bool is_equal_range_;
bool is_standard_range_;
bool is_precise_get_;
int64_t skip_scan_offset_;
};
struct ExprFinalInfo {
@ -408,6 +413,10 @@ public:
ObQueryRangeArray &ranges,
ObGetMethodArray &get_methods,
const common::ObDataTypeCastParams &dtc_params) const;
int get_ss_tablet_ranges(common::ObIAllocator &allocator,
ObExecContext &exec_ctx,
ObQueryRangeArray &ss_ranges,
const ObDataTypeCastParams &dtc_params) const;
int get_tablet_ranges(common::ObIAllocator &allocator,
ObExecContext &exec_ctx,
ObQueryRangeArray &ranges,
@ -447,7 +456,23 @@ public:
bool is_precise_get() const { return table_graph_.is_precise_get_; }
common::ObGeoRelationType get_geo_relation(ObItemType type) const;
const common::ObIArray<ObRawExpr*> &get_range_exprs() const { return range_exprs_; }
int check_graph_type();
const common::ObIArray<ObRawExpr*> &get_ss_range_exprs() const { return ss_range_exprs_; }
int check_graph_type(ObKeyPart &key_part_head);
int check_skip_scan_range(ObKeyPart *key_part_head,
const bool is_standard_range,
const int64_t max_precise_pos,
ObKeyPart *&ss_head,
int64_t &skip_scan_offset,
int64_t &ss_max_precise_pos);
int reset_skip_scan_range();
bool is_precise_get(const ObKeyPart &key_part_head,
int64_t &max_precise_pos,
bool ignore_head = false);
int fill_range_exprs(const int64_t max_precise_pos,
const int64_t ss_offset,
const int64_t ss_max_precise_pos);
bool is_ss_range() const { return table_graph_.skip_scan_offset_ > -1; }
int64_t get_skip_scan_offset() const { return table_graph_.skip_scan_offset_; }
static bool can_be_extract_range(ObItemType cmp_type, const ObExprResType &col_type,
const ObExprCalcType &res_type, common::ObObjType data_type,
@ -692,7 +717,8 @@ private:
inline int get_single_key_value(const ObKeyPart *key,
ObExecContext &exec_ctx,
ObSearchState &search_state,
const common::ObDataTypeCastParams &dtc_params) const;
const common::ObDataTypeCastParams &dtc_params,
int64_t skip_offset = 0) const;
int gen_simple_get_range(const ObKeyPart &root,
common::ObIAllocator &allocator,
ObExecContext &exec_ctx,
@ -704,6 +730,16 @@ private:
ObQueryRangeArray &ranges,
ObGetMethodArray &get_methods,
const common::ObDataTypeCastParams &dtc_params) const;
const ObKeyPart* get_ss_key_part_head() const;
int gen_skip_scan_range(ObIAllocator &allocator,
ObExecContext &exec_ctx,
const ObDataTypeCastParams &dtc_params,
const ObKeyPart *ss_root,
int64_t post_column_count,
ObQueryRangeArray &ss_ranges) const;
int cold_cast_cur_node(const ObKeyPart *cur,
common::ObIAllocator &allocator,
const common::ObDataTypeCastParams &dtc_params,
@ -768,6 +804,7 @@ private:
KeyPartStore key_part_store_;
//this flag used by optimizer, so don't need to serialize it
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> range_exprs_;
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> ss_range_exprs_;
MbrFilterArray mbr_filters_;
bool has_exec_param_;
bool is_equal_and_;

View File

@ -28,6 +28,7 @@ ob_set_subtarget(ob_storage blocksstable
blocksstable/ob_macro_block_writer.cpp
blocksstable/ob_data_macro_block_merge_writer.cpp
blocksstable/ob_micro_block_cache.cpp
blocksstable/ob_micro_block_hash_index.cpp
blocksstable/ob_micro_block_reader.cpp
blocksstable/ob_micro_block_row_exister.cpp
blocksstable/ob_micro_block_row_getter.cpp
@ -346,6 +347,8 @@ ob_set_subtarget(ob_storage access
access/ob_multiple_merge.cpp
access/ob_multiple_multi_scan_merge.cpp
access/ob_multiple_scan_merge.cpp
access/ob_multiple_skip_scan_merge.cpp
access/ob_multiple_multi_skip_scan_merge.cpp
access/ob_table_scan_iterator.cpp
access/ob_store_row_iterator.cpp
access/ob_i_sample_iterator.cpp

View File

@ -62,7 +62,7 @@ int ObAggCell::fill_result(sql::ObEvalCtx &ctx,bool need_padding)
} else {
sql::ObEvalInfo &eval_info = expr_->get_eval_info(ctx);
eval_info.evaluated_ = true;
LOG_DEBUG("fill result", K(result));
LOG_DEBUG("fill result", K(result), KPC(this));
}
return ret;
}
@ -119,7 +119,9 @@ int ObFirstRowAggCell::process(blocksstable::ObDatumRow &row)
{
int ret = OB_SUCCESS;
if (!aggregated_) {
if (OB_FAIL(datum_.deep_copy(row.storage_datums_[col_idx_], allocator_))) {
if (OB_FAIL(fill_default_if_need(row.storage_datums_[col_idx_]))) {
LOG_WARN("Failed to fill default", K(ret), K(*this));
} else if (OB_FAIL(datum_.deep_copy(row.storage_datums_[col_idx_], allocator_))) {
LOG_WARN("Failed to deep copy datum", K(ret), K(row), K(col_idx_));
} else {
aggregated_ = true;
@ -265,7 +267,191 @@ int ObCountAggCell::fill_result(sql::ObEvalCtx &ctx, bool need_padding)
result.set_int(row_count_);
eval_info.evaluated_ = true;
}
LOG_DEBUG("fill result", K(result));
LOG_DEBUG("fill result", K(result), KPC(this));
return ret;
}
ObAggDatumBuf::ObAggDatumBuf(common::ObIAllocator &allocator)
: size_(0), datums_(nullptr), buf_(nullptr), allocator_(allocator)
{
}
int ObAggDatumBuf::init(const int64_t size)
{
int ret = OB_SUCCESS;
void *buf = nullptr;
if (OB_ISNULL(buf = allocator_.alloc(sizeof(ObDatum) * size))) {
ret = common::OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Failed to alloc datum buf", K(ret), K(size));
} else if (FALSE_IT(datums_ = new (buf) ObDatum[size])) {
} else if (OB_ISNULL(buf = allocator_.alloc(common::OBJ_DATUM_NUMBER_RES_SIZE * size))) {
ret = common::OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Failed to alloc datum buf", K(ret), K(size));
} else {
buf_ = static_cast<char*>(buf);
size_ = size;
reuse();
}
return ret;
}
void ObAggDatumBuf::reset()
{
if (OB_NOT_NULL(datums_)) {
allocator_.free(datums_);
datums_ = nullptr;
}
if (OB_NOT_NULL(buf_)) {
allocator_.free(buf_);
buf_ = nullptr;
}
size_ = 0;
}
void ObAggDatumBuf::reuse()
{
for(int64_t i = 0; i < size_; ++i) {
datums_[i].pack_ = 0;
datums_[i].ptr_ = buf_ + i * common::OBJ_DATUM_NUMBER_RES_SIZE;
}
}
ObMinMaxAggCell::ObMinMaxAggCell(
bool is_min,
const int32_t col_idx,
const share::schema::ObColumnParam *col_param,
sql::ObExpr *expr,
common::ObIAllocator &allocator)
: ObAggCell(col_idx, col_param, expr, allocator),
is_min_(is_min),
agg_datum_buf_(allocator),
cell_data_ptrs_(nullptr),
datum_allocator_(ObModIds::OB_TABLE_SCAN_ITER)
{
datum_.set_null();
}
void ObMinMaxAggCell::reset()
{
agg_datum_buf_.reset();
if (nullptr != cell_data_ptrs_) {
allocator_.free(cell_data_ptrs_);
cell_data_ptrs_ = nullptr;
}
ObAggCell::reset();
}
void ObMinMaxAggCell::reuse()
{
datum_.reuse();
datum_.set_null();
ObAggCell::reuse();
}
int ObMinMaxAggCell::init(sql::ObPushdownOperator *op, sql::ObExpr *col_expr, const int64_t batch_size)
{
int ret = OB_SUCCESS;
const ObDatumCmpFuncType cmp_fun = expr_->basic_funcs_->null_first_cmp_;
if (OB_ISNULL(cmp_fun)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cmp_func is NULL", K(ret), KPC(expr_));
} else {
void *buf = nullptr;
cmp_fun_ = cmp_fun;
if (OB_FAIL(agg_datum_buf_.init(batch_size))) {
LOG_WARN("Failed to init agg datum buf", K(ret));
} else if (OB_ISNULL(buf = allocator_.alloc(sizeof(char*) * batch_size))) {
ret = common::OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Failed to alloc cell data ptrs", K(ret), K(batch_size));
} else {
cell_data_ptrs_ = static_cast<const char**> (buf);
}
}
return ret;
}
int ObMinMaxAggCell::process(blocksstable::ObDatumRow &row)
{
int ret = OB_SUCCESS;
blocksstable::ObStorageDatum &storage_datum = row.storage_datums_[col_idx_];
if (OB_FAIL(process(storage_datum))) {
LOG_WARN("Failed to process datum", K(ret), K(storage_datum), KPC(this));
}
LOG_DEBUG("after process single row", K(storage_datum), KPC(this));
return ret;
}
int ObMinMaxAggCell::process(
blocksstable::ObIMicroBlockReader *reader,
int64_t *row_ids,
const int64_t row_count)
{
int ret = OB_SUCCESS;
blocksstable::ObStorageDatum storage_datum;
storage_datum.set_null();
if (blocksstable::ObIMicroBlockReader::Reader == reader->get_type()) {
blocksstable::ObMicroBlockReader *block_reader = static_cast<blocksstable::ObMicroBlockReader*>(reader);
blocksstable::ObMicroBlockAggInfo<blocksstable::ObStorageDatum> agg_info(is_min_, cmp_fun_, storage_datum);
if (OB_FAIL(block_reader->get_min_or_max(col_idx_, col_param_, row_ids, row_count, agg_info))) {
LOG_WARN("Failed to get min or max", K(ret), K(row_count), KPC(this));
}
} else {
// agg_datum_buf_.reuse();
blocksstable::ObMicroBlockDecoder *block_decoder = static_cast<blocksstable::ObMicroBlockDecoder*>(reader);
blocksstable::ObMicroBlockAggInfo<common::ObDatum> agg_info(is_min_, cmp_fun_, storage_datum);
if (OB_FAIL(block_decoder->get_min_or_max(col_idx_, row_ids, cell_data_ptrs_, row_count, agg_datum_buf_.get_datums(), agg_info))) {
LOG_WARN("Failed to get min or max", K(ret), K(row_count), KPC(this));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(process(storage_datum))) {
LOG_WARN("Failed to process datum", K(ret), K(storage_datum), KPC(this));
}
}
LOG_DEBUG("after process batch rows", K(storage_datum), KPC(this));
return ret;
}
int ObMinMaxAggCell::process(const blocksstable::ObMicroIndexInfo &index_info)
{
int ret = OB_NOT_SUPPORTED;
return ret;
}
int ObMinMaxAggCell::process(blocksstable::ObStorageDatum &storage_datum)
{
int ret = OB_SUCCESS;
if (OB_FAIL(fill_default_if_need(storage_datum))) {
LOG_WARN("Failed to fill default", K(ret), K(storage_datum), K(*this));
} else if (datum_.is_null() && !storage_datum.is_null()) {
if (OB_FAIL(datum_.deep_copy(storage_datum, datum_allocator_))) {
LOG_WARN("Failed to deep copy datum", K(ret), K(storage_datum), K(col_idx_));
}
} else if (!storage_datum.is_null()) {
int cmp_ret = cmp_fun_(datum_, storage_datum);
if ((is_min_ && cmp_ret > 0) || (!is_min_ && cmp_ret < 0)) {
if (OB_FAIL(deep_copy_datum(storage_datum))) {
LOG_WARN("Failed to deep copy datum", K(ret), K(storage_datum), K(datum_), K(col_idx_));
}
}
}
return ret;
}
int ObMinMaxAggCell::deep_copy_datum(const blocksstable::ObStorageDatum &src)
{
int ret = OB_SUCCESS;
if (src.is_null() || src.is_nop()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Uexpected datum", K(ret), K(src));
} else {
if (!datum_.is_local_buf()) {
datum_allocator_.reuse();
}
if (OB_FAIL(datum_.deep_copy(src, datum_allocator_))) {
LOG_WARN("Failed to deep copy", K(ret), K(src), K(datum_));
}
}
return ret;
}
@ -347,9 +533,33 @@ int ObAggRow::init(const ObTableAccessParam &param)
} else if (OB_FAIL(agg_cells_.push_back(cell))) {
LOG_WARN("Failed to push back agg cell", K(ret), K(i));
}
} else if (T_FUN_MIN == expr->type_ || T_FUN_MAX == expr->type_) {
need_exclude_null_ = true;
const bool is_min = T_FUN_MIN == expr->type_;
const share::schema::ObColumnParam *col_param = out_cols_param->at(col_idx);
sql::ObExpr *col_expr = nullptr;
for (int64_t i = 0; OB_SUCC(ret) && i < param.output_exprs_->count(); ++i) {
if (param.iter_param_.out_cols_project_->at(i) == col_idx) {
col_expr = param.output_exprs_->at(i);
break;
}
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(col_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("ref col expr is null", K(ret), K(col_idx), K(i));
} else if (OB_ISNULL(buf = allocator_.alloc(sizeof(ObMinMaxAggCell))) ||
OB_ISNULL(cell = new(buf) ObMinMaxAggCell(is_min, col_idx, col_param, expr, allocator_))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Failed to alloc memroy for agg cell", K(ret), K(i));
} else if (OB_FAIL(static_cast<ObMinMaxAggCell*>(cell)->init(param.op_, col_expr, ObAggregatedStore::BATCH_SIZE))) {
LOG_WARN("Failed to init ObMinMaxAggCell", K(ret), KPC(cell));
} else if (OB_FAIL(agg_cells_.push_back(cell))) {
LOG_WARN("Failed to push back agg cell", K(ret), K(i));
}
} else {
ret = OB_NOT_SUPPORTED;
LOG_WARN("Agg min/max/sum is not supported", K(ret));
LOG_WARN("Agg is not supported", K(ret), K(expr->type_));
}
}
}
@ -360,7 +570,9 @@ int ObAggRow::init(const ObTableAccessParam &param)
ObAggregatedStore::ObAggregatedStore(const int64_t batch_size, sql::ObEvalCtx &eval_ctx, ObTableAccessContext &context)
: ObBlockBatchedRowStore(batch_size, eval_ctx, context),
is_firstrow_aggregated_(false),
agg_row_(*context_.stmt_allocator_)
agg_row_(*context_.stmt_allocator_),
agg_flat_row_mode_(false),
row_buf_()
{
}
@ -374,6 +586,8 @@ void ObAggregatedStore::reset()
ObBlockBatchedRowStore::reset();
agg_row_.reset();
is_firstrow_aggregated_ = false;
agg_flat_row_mode_ = false;
row_buf_.reset();
}
void ObAggregatedStore::reuse()
@ -404,6 +618,11 @@ int ObAggregatedStore::init(const ObTableAccessParam &param)
LOG_WARN("Failed to init ObBlockBatchedRowStore", K(ret));
} else if (OB_FAIL(agg_row_.init(param))) {
LOG_WARN("Failed to init agg cells", K(ret));
} else if (OB_FAIL(check_agg_in_row_mode(param.iter_param_))) {
LOG_WARN("Failed to check agg in row mode", K(ret));
} else if (agg_flat_row_mode_ &&
OB_FAIL(row_buf_.init(*context_.stmt_allocator_, param.iter_param_.get_full_out_col_cnt()))) {
LOG_WARN("Fail to init datum row buf", K(ret));
}
if (OB_FAIL(ret)) {
reset();
@ -411,6 +630,36 @@ int ObAggregatedStore::init(const ObTableAccessParam &param)
return ret;
}
int ObAggregatedStore::check_agg_in_row_mode(const ObTableIterParam &iter_param)
{
int ret = OB_SUCCESS;
int64_t agg_cnt = 0;
ObAggCell *cell = nullptr;
const ObTableReadInfo *read_info = nullptr;
if (OB_ISNULL(read_info = iter_param.get_read_info())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpected null read info", K(ret), K(iter_param));
}
for (int64_t i = 0; OB_SUCC(ret) && i < agg_row_.get_agg_count(); ++i) {
if (OB_ISNULL(cell = agg_row_.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpecte null agg cell", K(ret), K(i));
} else if (OB_COUNT_AGG_PD_COLUMN_ID == cell->get_col_idx()) {
} else if (cell->get_col_idx() >= read_info->get_request_count()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpected col idx", K(ret), K(i), KPC(cell), K(read_info->get_request_count()));
} else if (ObAggCell::FIRST_ROW != cell->get_type()) {
agg_cnt++;
}
}
if (OB_SUCC(ret)) {
agg_flat_row_mode_ =
agg_cnt > AGG_ROW_MODE_COUNT_THRESHOLD ||
(double) agg_cnt/read_info->get_request_count() > AGG_ROW_MODE_RATIO_THRESHOLD;
}
return ret;
}
int ObAggregatedStore::fill_index_info(const blocksstable::ObMicroIndexInfo &index_info)
{
int ret = OB_SUCCESS;
@ -468,6 +717,13 @@ int ObAggregatedStore::fill_rows(
if (OB_UNLIKELY(OB_ITER_END != ret)) {
LOG_WARN("Failed to get row ids", K(ret), K(begin_index), K(end_index));
}
} else if (0 == row_count) {
} else if (agg_flat_row_mode_ && blocksstable::ObIMicroBlockReader::Reader == reader->get_type()) {
// for flat block, do aggregate in row mode
blocksstable::ObMicroBlockReader *block_reader = static_cast<blocksstable::ObMicroBlockReader*>(reader);
if (OB_FAIL(block_reader->get_aggregate_result(row_ids_, row_count, row_buf_, agg_row_.get_agg_cells()))) {
LOG_WARN("Failed to process aggregates", K(ret));
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < agg_row_.get_agg_count(); ++i) {
ObAggCell *cell = agg_row_.at(i);

View File

@ -29,9 +29,18 @@ struct ObMicroIndexInfo;
namespace storage
{
static const int64_t AGG_ROW_MODE_COUNT_THRESHOLD = 3;
static const double AGG_ROW_MODE_RATIO_THRESHOLD = 0.5;
class ObAggCell
{
public:
enum ObAggCellType
{
COUNT,
MINMAX,
FIRST_ROW,
};
ObAggCell(
const int32_t col_idx,
const share::schema::ObColumnParam *col_param,
@ -40,6 +49,7 @@ public:
virtual ~ObAggCell();
virtual void reset();
virtual void reuse();
virtual ObAggCellType get_type() const = 0;
virtual int process(blocksstable::ObDatumRow &row) = 0;
virtual int process(
blocksstable::ObIMicroBlockReader *reader,
@ -47,6 +57,7 @@ public:
const int64_t row_count) = 0;
virtual int process(const blocksstable::ObMicroIndexInfo &index_info) = 0;
virtual int fill_result(sql::ObEvalCtx &ctx, bool need_padding);
OB_INLINE int32_t get_col_idx() const { return col_idx_; }
TO_STRING_KV(K_(col_idx), K_(datum), KPC(col_param_), K_(expr));
protected:
int fill_default_if_need(blocksstable::ObStorageDatum &datum);
@ -69,6 +80,7 @@ public:
common::ObIAllocator &allocator);
virtual ~ObFirstRowAggCell() { reset(); };
virtual void reset() override;
virtual ObAggCellType get_type() const override { return FIRST_ROW; }
virtual int process(blocksstable::ObDatumRow &row) override;
virtual int process(
blocksstable::ObIMicroBlockReader *reader,
@ -76,7 +88,7 @@ public:
const int64_t row_count) override;
virtual int process(const blocksstable::ObMicroIndexInfo &index_info) override;
virtual int fill_result(sql::ObEvalCtx &ctx, bool need_padding) override;
TO_STRING_KV(K_(col_idx), K_(datum), K_(col_param), K_(expr), K_(aggregated));
INHERIT_TO_STRING_KV("ObAggCell", ObAggCell, K_(aggregated));
private:
bool aggregated_;
};
@ -93,6 +105,7 @@ public:
virtual ~ObCountAggCell() { reset(); };
virtual void reset() override;
virtual void reuse() override;
virtual ObAggCellType get_type() const override { return COUNT; }
virtual int process(blocksstable::ObDatumRow &row) override;
virtual int process(
blocksstable::ObIMicroBlockReader *reader,
@ -100,12 +113,60 @@ public:
const int64_t row_count) override;
virtual int process(const blocksstable::ObMicroIndexInfo &index_info) override;
virtual int fill_result(sql::ObEvalCtx &ctx, bool need_padding) override;
TO_STRING_KV(K_(col_idx), K_(datum), K_(col_param), K_(expr), K_(exclude_null), K_(row_count));
INHERIT_TO_STRING_KV("ObAggCell", ObAggCell, K_(exclude_null), K_(row_count));
private:
bool exclude_null_;
int64_t row_count_;
};
// TODO sum/min/max
class ObAggDatumBuf {
public:
ObAggDatumBuf(common::ObIAllocator &allocator);
~ObAggDatumBuf() { reset(); };
int init(const int64_t size);
void reuse();
void reset();
OB_INLINE ObDatum *get_datums() { return datums_; }
TO_STRING_KV(K_(size), K_(datums), K_(buf));
private:
int64_t size_;
ObDatum *datums_;
char *buf_;
common::ObIAllocator &allocator_;
};
class ObMinMaxAggCell : public ObAggCell
{
public:
ObMinMaxAggCell(
bool is_min,
const int32_t col_idx,
const share::schema::ObColumnParam *col_param,
sql::ObExpr *expr,
common::ObIAllocator &allocator);
virtual ~ObMinMaxAggCell() { reset(); };
virtual void reset() override;
virtual void reuse() override;
virtual ObAggCellType get_type() const override { return MINMAX; }
int init(sql::ObPushdownOperator *op, sql::ObExpr *col_expr, const int64_t batch_size);
virtual int process(blocksstable::ObDatumRow &row) override;
virtual int process(
blocksstable::ObIMicroBlockReader *reader,
int64_t *row_ids,
const int64_t row_count) override;
virtual int process(const blocksstable::ObMicroIndexInfo &index_info) override;
INHERIT_TO_STRING_KV("ObAggCell", ObAggCell, K_(is_min), K_(cmp_fun), K_(agg_datum_buf));
private:
int deep_copy_datum(const blocksstable::ObStorageDatum &src);
int process(blocksstable::ObStorageDatum &datum);
bool is_min_;
ObDatumCmpFuncType cmp_fun_;
ObAggDatumBuf agg_datum_buf_;
const char **cell_data_ptrs_;
common::ObArenaAllocator datum_allocator_;
};
// TODO sum
class ObAggRow
{
@ -119,7 +180,8 @@ public:
bool need_exclude_null() const { return need_exclude_null_; };
// void set_firstrow_aggregated(bool aggregated) { is_firstrow_aggregated_ = aggregated; }
// bool is_firstrow_aggregated() const { return is_firstrow_aggregated_; }
ObAggCell* at(int64_t idx) { return agg_cells_.at(idx); }
OB_INLINE ObAggCell* at(int64_t idx) { return agg_cells_.at(idx); }
OB_INLINE common::ObIArray<ObAggCell*>& get_agg_cells() { return agg_cells_; }
TO_STRING_KV(K_(agg_cells));
private:
common::ObFixedArray<ObAggCell *, common::ObIAllocator> agg_cells_;
@ -158,11 +220,14 @@ public:
!index_info.is_right_border();
}
OB_INLINE void set_end() { iter_end_flag_ = IterEndState::ITER_END; }
TO_STRING_KV(K_(agg_row));
int check_agg_in_row_mode(const ObTableIterParam &iter_param);
TO_STRING_KV(K_(is_firstrow_aggregated), K_(agg_row), K_(agg_flat_row_mode), K_(row_buf));
private:
bool is_firstrow_aggregated_;
ObAggRow agg_row_;
bool agg_flat_row_mode_;
blocksstable::ObDatumRow row_buf_;
};
} /* namespace storage */

View File

@ -269,6 +269,7 @@ DEF_TO_STRING(ObTableScanParam)
N_COLUMN_IDS, column_ids_,
N_INDEX_ID, index_id_,
N_KEY_RANGES, key_ranges_,
K_(ss_key_ranges),
K_(range_array_pos),
N_TIMEOUT, timeout_,
N_SCAN_FLAG, scan_flag_,
@ -287,7 +288,8 @@ DEF_TO_STRING(ObTableScanParam)
K_(snapshot),
KPC_(table_param),
K_(sample_info),
K_(need_scn));
K_(need_scn),
K_(need_switch_param));
J_OBJ_END();
return pos;
}

View File

@ -153,7 +153,11 @@ public:
OB_INLINE virtual bool is_valid() const {
return snapshot_.valid_ && ObVTableScanParam::is_valid();
}
OB_INLINE bool use_index_skip_scan() const {
return (1 == ss_key_ranges_.count()) && (!ss_key_ranges_.at(0).is_whole_range());
}
bool is_thread_scope_;
ObRangeArray ss_key_ranges_; // used for index skip scan, use as postfix range for ObVTableScanParam::key_ranges_
DECLARE_VIRTUAL_TO_STRING;
private:

View File

@ -303,7 +303,7 @@ int ObIndexTreePrefetcher::prefetch_block_data(
macro_id == micro_handle.macro_block_id_ &&
offset == micro_handle.micro_info_.offset_ &&
index_block_info.row_header_->get_block_size() == micro_handle.micro_info_.size_) {
LOG_DEBUG("Cur micro handle is still valid");
LOG_DEBUG("Cur micro handle is still valid", K(index_block_info), K(micro_handle));
if (is_data) {
EVENT_INC(ObStatEventIds::DATA_BLOCK_CACHE_HIT);
} else {
@ -366,6 +366,14 @@ int ObIndexTreePrefetcher::prefetch_block_data(
micro_handle.macro_block_id_ = macro_id;
micro_handle.block_state_ = ObSSTableMicroBlockState::IN_BLOCK_IO;
micro_handle.io_handle_ = macro_handle;
if (is_data && OB_FAIL(micro_block_handle_mgr_.put_micro_block_handle(
tenant_id,
macro_id,
*index_block_info.row_header_,
micro_handle))) {
STORAGE_LOG(WARN, "failed to put handle cache", K(ret), K(tenant_id), K(macro_id), K(index_block_info));
}
}
}
}
@ -379,6 +387,256 @@ int ObIndexTreePrefetcher::prefetch_block_data(
return ret;
}
////////////////////////////////// ObIndexTreeMultiPrefetcher /////////////////////////////////////////////
void ObIndexTreeMultiPrefetcher::reset()
{
ObIndexTreePrefetcher::reset();
fetch_rowkey_idx_ = 0;
prefetch_rowkey_idx_ = 0;
prefetched_rowkey_cnt_ = 0;
rowkeys_ = nullptr;
ext_read_handles_.reset();
}
void ObIndexTreeMultiPrefetcher::reuse()
{
ObIndexTreePrefetcher::reuse();
fetch_rowkey_idx_ = 0;
prefetch_rowkey_idx_ = 0;
prefetched_rowkey_cnt_ = 0;
rowkeys_ = nullptr;
}
int ObIndexTreeMultiPrefetcher::init(
const int iter_type,
ObSSTable &sstable,
const ObTableIterParam &iter_param,
ObTableAccessContext &access_ctx,
const void *query_range)
{
int ret = OB_SUCCESS;
if (IS_INIT) {
ret = OB_INIT_TWICE;
LOG_WARN("ObIndexTreeMultiPrefetcher has been inited", K(ret));
} else if (OB_UNLIKELY(ObStoreRowIterator::IteratorMultiGet != iter_type)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Invalid argument", K(ret), K(iter_type));
} else {
sstable_ = &sstable;
access_ctx_ = &access_ctx;
iter_param_ = &iter_param;
index_read_info_ = iter_param.get_full_read_info()->get_index_read_info();
data_version_ = sstable_->is_major_sstable() ? sstable_->get_snapshot_version() : sstable_->get_key().get_end_scn().get_val_for_tx();
data_block_cache_ = &(ObStorageCacheSuite::get_instance().get_block_cache());
index_block_cache_ = &(ObStorageCacheSuite::get_instance().get_index_block_cache());
ext_read_handles_.set_allocator(access_ctx.stmt_allocator_);
rowkeys_ = static_cast<const common::ObIArray<blocksstable::ObDatumRowkey> *> (query_range);
index_tree_height_ = sstable_->get_meta().get_index_tree_height();
int32_t range_count = rowkeys_->count();
max_handle_prefetching_cnt_ = min(range_count, MAX_MULTIGET_MICRO_DATA_HANDLE_CNT);
if (0 == range_count) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("range count should be greater than 0", K(ret), K(range_count));
} else if (OB_FAIL(ext_read_handles_.prepare_reallocate(max_handle_prefetching_cnt_))) {
LOG_WARN("Fail to init read_handles", K(ret), K(max_handle_prefetching_cnt_));
} else if (OB_FAIL(micro_block_handle_mgr_.init(range_count > 1, false, *access_ctx.stmt_allocator_))) {
LOG_WARN("failed to init block handle mgr", K(ret));
} else {
is_inited_ = true;
}
}
return ret;
}
int ObIndexTreeMultiPrefetcher::switch_context(
const int iter_type,
const ObTableReadInfo &index_read_info,
ObSSTable &sstable,
ObTableAccessContext &access_ctx,
const void *query_range)
{
int ret = OB_SUCCESS;
bool is_multi_range = false;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
LOG_WARN("not inited", K(ret));
} else if (OB_UNLIKELY(ObStoreRowIterator::IteratorMultiGet != iter_type)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Invalid argument", K(ret), K(iter_type));
} else {
sstable_ = &sstable;
access_ctx_ = &access_ctx;
data_version_ = sstable_->is_major_sstable() ? sstable_->get_snapshot_version() : sstable_->get_key().get_end_scn().get_val_for_tx();
rowkeys_ = static_cast<const common::ObIArray<blocksstable::ObDatumRowkey> *> (query_range);
index_read_info_ = &index_read_info;
max_handle_prefetching_cnt_ = min(rowkeys_->count(), MAX_MULTIGET_MICRO_DATA_HANDLE_CNT);
if (OB_FAIL(ext_read_handles_.prepare_reallocate(max_handle_prefetching_cnt_))) {
LOG_WARN("Fail to init read_handles", K(ret), K(max_handle_prefetching_cnt_));
} else if (!is_rescan_) {
is_rescan_ = true;
for (int64_t i = 0; i < ext_read_handles_.count(); ++i) {
ext_read_handles_.at(i).reset();
}
micro_block_handle_mgr_.reset();
if (OB_FAIL(micro_block_handle_mgr_.init(true, false, *access_ctx.stmt_allocator_))) {
LOG_WARN("failed to init block handle mgr", K(ret));
}
}
}
return ret;
}
int ObIndexTreeMultiPrefetcher::multi_prefetch()
{
int ret = OB_SUCCESS;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
LOG_WARN("ObIndexTreeMultiPrefetcher not init", K(ret));
} else {
const int64_t rowkey_cnt = rowkeys_->count();
for (int64_t i = fetch_rowkey_idx_;
OB_SUCC(ret) && prefetched_rowkey_cnt_ < rowkey_cnt && i < fetch_rowkey_idx_ + max_handle_prefetching_cnt_;
++i) {
const bool is_rowkey_to_fetched = i == fetch_rowkey_idx_;
const bool is_empty_handle = i >= prefetch_rowkey_idx_;
ObSSTableReadHandleExt &read_handle = ext_read_handles_[i % max_handle_prefetching_cnt_];
if (is_empty_handle && prefetch_rowkey_idx_ < rowkey_cnt) {
read_handle.reuse();
read_handle.rowkey_ = &rowkeys_->at(prefetch_rowkey_idx_);
read_handle.range_idx_ = prefetch_rowkey_idx_;
read_handle.is_get_ = true;
prefetch_rowkey_idx_++;
if (OB_FAIL(lookup_in_cache(read_handle))) {
LOG_WARN("Failed to lookup_in_cache", K(ret));
} else if (ObSSTableRowState::IN_BLOCK == read_handle.row_state_) {
if (OB_FAIL(sstable_->get_index_tree_root(*index_read_info_, index_block_))) {
LOG_WARN("Fail to get index block root", K(ret));
} else if (!index_scanner_.is_valid() && OB_FAIL(init_index_scanner(index_scanner_))) {
LOG_WARN("Fail to init index scanner", K(ret));
} else if (OB_FAIL(drill_down(ObIndexBlockRowHeader::DEFAULT_IDX_ROW_MACRO_ID, read_handle, false, is_rowkey_to_fetched))) {
LOG_WARN("Fail to prefetch next level", K(ret), K(index_block_), K(read_handle), KPC(this));
} else {
EVENT_INC(ObStatEventIds::INDEX_BLOCK_READ_CNT);
}
} else {
mark_cur_rowkey_prefetched(read_handle);
}
} else if (read_handle.cur_prefetch_end_) {
continue;
} else if (read_handle.cur_level_ >= index_tree_height_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Fail to prefetch, unexpected cur level", K(ret), K(read_handle.cur_level_), K(index_tree_height_), K(read_handle), KPC(this));
} else if (ObSSTableRowState::IN_BLOCK == read_handle.row_state_) {
bool stop_prefetch = false;
int64_t tenant_id = MTL_ID();
ObMicroIndexInfo &cur_index_info = read_handle.index_block_info_;
ObMicroBlockDataHandle &next_handle = read_handle.get_read_handle();
if (OB_UNLIKELY(!cur_index_info.is_valid() ||
nullptr == read_handle.micro_handle_ ||
&next_handle == read_handle.micro_handle_ ||
ObSSTableMicroBlockState::IN_BLOCK_IO != read_handle.micro_handle_->block_state_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Fail to prefetch, unexpected read handle", K(ret), K(read_handle), KPC(this));
} else if (OB_FAIL(micro_block_handle_mgr_.get_micro_block_handle(
tenant_id,
cur_index_info,
cur_index_info.is_data_block(),
next_handle))) {
//not in cache yet, stop this rowkey prefetching if it's not the rowkey to be feteched
ret = OB_SUCCESS;
if (is_rowkey_to_fetched) {
if (OB_FAIL(read_handle.micro_handle_->get_index_block_data(*index_read_info_, index_block_))) {
LOG_WARN("Fail to get index block data", K(ret), KPC(read_handle.micro_handle_));
}
} else {
stop_prefetch = true;
}
} else if (FALSE_IT(read_handle.set_cur_micro_handle(next_handle))) {
} else if (OB_FAIL(read_handle.micro_handle_->get_cached_index_block_data(*index_read_info_, index_block_))) {
LOG_WARN("Fail to get cached index block data", K(ret), KPC(read_handle.micro_handle_));
}
if (OB_SUCC(ret) && !stop_prefetch) {
if (OB_FAIL(drill_down(cur_index_info.get_macro_id(), read_handle, cur_index_info.is_leaf_block(), is_rowkey_to_fetched))) {
LOG_WARN("Fail to prefetch next level", K(ret), K(index_block_), K(read_handle), KPC(this));
}
}
}
}
}
return ret;
}
int ObIndexTreeMultiPrefetcher::drill_down(
const MacroBlockId &macro_id,
ObSSTableReadHandleExt &read_handle,
const bool cur_level_is_leaf,
const bool force_prefetch)
{
int ret = OB_SUCCESS;
ObMicroIndexInfo index_block_info;
EVENT_INC(ObStatEventIds::INDEX_BLOCK_READ_CNT);
read_handle.cur_level_++;
if (OB_FAIL(index_scanner_.open(macro_id, index_block_, *read_handle.rowkey_, read_handle.range_idx_))) {
LOG_WARN("Fail to open index block scanner", K(ret), K(index_block_), K(read_handle));
} else if (cur_level_is_leaf && read_handle.cur_level_ != index_tree_height_ - 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Fail to prefetch, unexpected level", K(ret), K(cur_level_is_leaf),
K(read_handle.cur_level_), K(index_tree_height_));
} else if (OB_FAIL(index_scanner_.get_next(index_block_info))) {
if (OB_UNLIKELY(OB_ITER_END != ret)) {
LOG_WARN("Fail to get index block row", K(ret), K_(index_scanner));
} else {
mark_cur_rowkey_prefetched(read_handle);
read_handle.row_state_ = ObSSTableRowState::NOT_EXIST;
ret = OB_SUCCESS;
}
} else if (cur_level_is_leaf != index_block_info.is_data_block()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Fail to prefetch, unexpected level", K(ret), K(cur_level_is_leaf), K(index_block_info));
} else if (index_block_info.is_macro_node() && OB_FAIL(check_bloom_filter(index_block_info, read_handle))) {
LOG_WARN("Fail to check bloom filter", K(ret), K(index_block_info), K(read_handle));
} else if (ObSSTableRowState::NOT_EXIST == read_handle.row_state_) {
mark_cur_rowkey_prefetched(read_handle);
} else {
// hold block cache of the parent temporaliy to avoid freed
ObMicroBlockDataHandle &next_handle = read_handle.get_read_handle();
if (OB_FAIL(prefetch_block_data(index_block_info, next_handle, cur_level_is_leaf))) {
LOG_WARN("fail to prefetch_block_data", K(ret), K(read_handle), K(index_block_info), K(cur_level_is_leaf));
} else if (FALSE_IT(read_handle.set_cur_micro_handle(next_handle))) {
} else if (cur_level_is_leaf) {
mark_cur_rowkey_prefetched(read_handle);
read_handle.index_block_info_ = index_block_info;
} else if (force_prefetch || ObSSTableMicroBlockState::IN_BLOCK_CACHE == next_handle.block_state_) {
if (ObSSTableMicroBlockState::IN_BLOCK_CACHE == next_handle.block_state_) {
LOG_DEBUG("cur handle is in cache", K(read_handle), K(index_block_info), K(next_handle));
if (OB_FAIL(next_handle.get_cached_index_block_data(*index_read_info_, index_block_))) {
LOG_WARN("Fail to get index block data", K(ret), K(next_handle));
}
} else {
LOG_DEBUG("cur handle is not in cache, force prefetch", K(read_handle), K(index_block_info), K(next_handle));
if (OB_FAIL(next_handle.get_index_block_data(*index_read_info_, index_block_))) {
LOG_WARN("Fail to get index block data", K(ret), K(next_handle));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(drill_down(
index_block_info.get_macro_id(),
read_handle,
index_block_info.is_leaf_block(),
force_prefetch))) {
LOG_WARN("Faile to prefetch data block", K(ret), K(read_handle));
}
}
} else {
LOG_DEBUG("cur handle is not in cache, has submit io", K(read_handle), K(index_block_info), K(next_handle));
read_handle.index_block_info_ = index_block_info;
}
}
return ret;
}
////////////////////////////////// MultiPassPrefetcher /////////////////////////////////////////////
void ObIndexTreeMultiPassPrefetcher::reset()

View File

@ -91,7 +91,7 @@ public:
return ret;
}
TO_STRING_KV(K_(is_get), K_(is_bf_contain), K_(row_state), K_(range_idx),
K_(micro_begin_idx), K_(micro_end_idx), KP_(query_range));
K_(micro_begin_idx), K_(micro_end_idx), KP_(query_range), KPC_(micro_handle));
public:
bool is_get_;
@ -185,13 +185,119 @@ protected:
const ObTableReadInfo *index_read_info_;
common::ObFixedArray<int32_t, common::ObIAllocator> agg_projector_;
common::ObFixedArray<share::schema::ObColumnSchemaV2, common::ObIAllocator> agg_column_schema_;
private:
static const int64_t DEFAULT_GET_MICRO_DATA_HANDLE_CNT = 2;
ObIndexBlockRowScanner index_scanner_;
private:
ObMicroBlockDataHandle micro_handles_[DEFAULT_GET_MICRO_DATA_HANDLE_CNT];
MacroBlockId macro_id_;
};
class ObIndexTreeMultiPrefetcher : public ObIndexTreePrefetcher
{
public:
static const int32_t MAX_MULTIGET_MICRO_DATA_HANDLE_CNT = 32;
struct ObSSTableReadHandleExt : public ObSSTableReadHandle {
ObSSTableReadHandleExt() :
ObSSTableReadHandle(),
cur_level_(-1),
cur_prefetch_end_(false),
index_block_info_(),
micro_handle_idx_(0)
{}
~ObSSTableReadHandleExt()
{}
void reuse()
{
ObSSTableReadHandle::reuse();
cur_level_ = -1;
cur_prefetch_end_ = false;
index_block_info_.reset();
micro_handle_idx_ = 0;
}
void reset()
{
ObSSTableReadHandle::reset();
cur_level_ = -1;
cur_prefetch_end_ = false;
index_block_info_.reset();
micro_handle_idx_ = 0;
for (int64_t i = 0; i < DEFAULT_GET_MICRO_DATA_HANDLE_CNT; ++i) {
micro_handles_[i].reset();
}
}
OB_INLINE ObMicroBlockDataHandle& get_read_handle()
{
return micro_handles_[micro_handle_idx_ % DEFAULT_GET_MICRO_DATA_HANDLE_CNT];
}
OB_INLINE void set_cur_micro_handle(ObMicroBlockDataHandle &handle)
{
micro_handle_ = &handle;
micro_handle_idx_++;
}
INHERIT_TO_STRING_KV("ObSSTableReadHandle", ObSSTableReadHandle, KPC_(rowkey),
K_(cur_level), K_(cur_prefetch_end), K_(index_block_info), K_(micro_handle_idx), K_(micro_handles));
int16_t cur_level_;
bool cur_prefetch_end_;
ObMicroIndexInfo index_block_info_;
int64_t micro_handle_idx_;
ObMicroBlockDataHandle micro_handles_[DEFAULT_GET_MICRO_DATA_HANDLE_CNT];
};
typedef ObReallocatedFixedArray<ObSSTableReadHandleExt> ReadHandleExtArray;
ObIndexTreeMultiPrefetcher() :
index_tree_height_(0),
fetch_rowkey_idx_(0),
prefetch_rowkey_idx_(0),
prefetched_rowkey_cnt_(0),
rowkeys_(nullptr),
ext_read_handles_()
{}
virtual ~ObIndexTreeMultiPrefetcher() { reset(); }
virtual void reset() override;
virtual void reuse() override;
virtual int init(
const int iter_type,
ObSSTable &sstable,
const ObTableIterParam &iter_param,
ObTableAccessContext &access_ctx,
const void *query_range) override;
virtual int switch_context(
const int iter_type,
const ObTableReadInfo &index_read_info,
ObSSTable &sstable,
ObTableAccessContext &access_ctx,
const void *query_range) override;
int multi_prefetch();
OB_INLINE bool is_prefetch_end() { return prefetched_rowkey_cnt_ >= rowkeys_->count(); }
OB_INLINE void mark_cur_rowkey_prefetched(ObSSTableReadHandleExt &read_handle)
{
read_handle.cur_prefetch_end_ = true;
prefetched_rowkey_cnt_++;
}
OB_INLINE void mark_cur_rowkey_fetched(ObSSTableReadHandleExt &read_handle)
{
fetch_rowkey_idx_++;
}
OB_INLINE ObSSTableReadHandleExt &current_read_handle()
{ return ext_read_handles_[fetch_rowkey_idx_ % MAX_MULTIGET_MICRO_DATA_HANDLE_CNT]; }
OB_INLINE ObMicroBlockDataHandle &current_micro_handle()
{ return *ext_read_handles_[fetch_rowkey_idx_ % MAX_MULTIGET_MICRO_DATA_HANDLE_CNT].micro_handle_; }
INHERIT_TO_STRING_KV("ObIndexTreePrefetcher", ObIndexTreePrefetcher, K_(index_tree_height),
K_(fetch_rowkey_idx), K_(prefetch_rowkey_idx), K_(prefetched_rowkey_cnt), K_(max_handle_prefetching_cnt));
int16_t index_tree_height_;
int32_t fetch_rowkey_idx_;
int32_t prefetch_rowkey_idx_;
int64_t prefetched_rowkey_cnt_;
int32_t max_handle_prefetching_cnt_;
const common::ObIArray<blocksstable::ObDatumRowkey> *rowkeys_;
ReadHandleExtArray ext_read_handles_;
private:
int drill_down(
const MacroBlockId &macro_id,
ObSSTableReadHandleExt &read_handle,
const bool cur_level_is_leaf,
const bool force_prefetch);
};
class ObIndexTreeMultiPassPrefetcher : public ObIndexTreePrefetcher
{
public:

View File

@ -107,8 +107,6 @@ int ObMultipleMerge::init(
STORAGE_LOG(WARN, "Failed to init datum row", K(ret));
} else if (OB_FAIL(unprojected_row_.init(*context.stmt_allocator_, param.get_out_col_cnt()))) {
STORAGE_LOG(WARN, "Failed to init datum row", K(ret));
} else if (OB_FAIL(full_row_.init(*context.stmt_allocator_, param.get_max_out_col_cnt()))) {
STORAGE_LOG(WARN, "Failed to init datum row", K(ret));
} else if (OB_FAIL(nop_pos_.init(*context.stmt_allocator_, param.get_max_out_col_cnt()))) {
STORAGE_LOG(WARN, "Fail to init nop pos, ", K(ret));
} else if (NULL != param.op_ && (NULL == param.output_exprs_ || NULL == param.row2exprs_projector_
@ -140,7 +138,6 @@ int ObMultipleMerge::init(
for (int64_t i = cur_row_.get_column_count(); i < param.get_out_col_cnt(); ++i) {
cur_row_.storage_datums_[i].set_nop();
}
full_row_.count_ = param.get_max_out_col_cnt();
unprojected_row_.count_ = 0;
get_table_param_ = get_table_param;
if (OB_SUCC(ret)) {

View File

@ -122,7 +122,6 @@ protected:
common::ObSEArray<storage::ObITable *, common::DEFAULT_STORE_CNT_IN_STORAGE> tables_;
blocksstable::ObDatumRow cur_row_;
blocksstable::ObDatumRow unprojected_row_;
blocksstable::ObDatumRow full_row_;
const ObIArray<int32_t> *out_cols_projector_;
int64_t curr_scan_index_;
blocksstable::ObDatumRowkey curr_rowkey_;

View File

@ -0,0 +1,124 @@
// Copyright (c) 2021 OceanBase
// OceanBase 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.
#include "ob_multiple_multi_skip_scan_merge.h"
namespace oceanbase
{
namespace storage
{
ObMultipleMultiSkipScanMerge::ObMultipleMultiSkipScanMerge()
: cur_range_idx_(0),
ranges_(nullptr),
skip_scan_ranges_(nullptr)
{
}
ObMultipleMultiSkipScanMerge::~ObMultipleMultiSkipScanMerge()
{
reset();
}
int ObMultipleMultiSkipScanMerge::init(
const ObTableAccessParam &param,
ObTableAccessContext &context,
const ObGetTableParam &get_table_param)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObMultipleSkipScanMerge::init(param, context, get_table_param))) {
STORAGE_LOG(WARN, "Fail to init ObMultipleSkipScanMerge", K(ret), K(context), K(get_table_param));
}
return ret;
}
void ObMultipleMultiSkipScanMerge::reset()
{
cur_range_idx_ = 0;
ranges_ = nullptr;
skip_scan_ranges_ = nullptr;
ObMultipleSkipScanMerge::reset();
}
void ObMultipleMultiSkipScanMerge::reuse()
{
cur_range_idx_ = 0;
ranges_ = nullptr;
skip_scan_ranges_ = nullptr;
ObMultipleSkipScanMerge::reuse();
}
int ObMultipleMultiSkipScanMerge::open(
const common::ObIArray<blocksstable::ObDatumRange> &ranges,
const common::ObIArray<blocksstable::ObDatumRange> &skip_scan_ranges)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ranges.count() != skip_scan_ranges.count() || ranges.count() == 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument", K(ret), K(ranges.count()), K(skip_scan_ranges.count()));
} else if (OB_FAIL(ObMultipleSkipScanMerge::open(ranges.at(cur_range_idx_), skip_scan_ranges.at(cur_range_idx_)))) {
STORAGE_LOG(WARN, "Fail to open cur range", K(ret), K(cur_range_idx_));
} else {
ranges_ = &ranges;
skip_scan_ranges_ = &skip_scan_ranges;
}
return ret;
}
int ObMultipleMultiSkipScanMerge::inner_get_next_row(blocksstable::ObDatumRow &row)
{
int ret = OB_SUCCESS;
while (OB_SUCC(ret)) {
if (OB_FAIL(ObMultipleSkipScanMerge::inner_get_next_row(row))) {
if (OB_UNLIKELY(OB_ITER_END != ret && OB_PUSHDOWN_STATUS_CHANGED != ret)) {
STORAGE_LOG(WARN, "Fail to inner get next row", K(ret), K(cur_range_idx_));
} else if (OB_ITER_END == ret) {
if (++cur_range_idx_ < ranges_->count()) {
ret = OB_SUCCESS;
ObMultipleSkipScanMerge::reuse();
if (OB_FAIL(ObMultipleSkipScanMerge::open(ranges_->at(cur_range_idx_), skip_scan_ranges_->at(cur_range_idx_)))) {
STORAGE_LOG(WARN, "Fail to open cur range", K(ret), K(cur_range_idx_));
}
}
}
} else {
STORAGE_LOG(DEBUG, "get next row", K(row));
break;
}
}
return ret;
}
int ObMultipleMultiSkipScanMerge::inner_get_next_rows()
{
int ret = OB_SUCCESS;
while (OB_SUCC(ret)) {
if (OB_FAIL(ObMultipleSkipScanMerge::inner_get_next_rows())) {
if (OB_UNLIKELY(OB_ITER_END != ret && OB_PUSHDOWN_STATUS_CHANGED != ret)) {
STORAGE_LOG(WARN, "Fail to inner get next row", K(ret), K(cur_range_idx_));
} else if (OB_ITER_END == ret) {
if (++cur_range_idx_ < ranges_->count()) {
ret = OB_SUCCESS;
ObMultipleSkipScanMerge::reuse();
if (OB_FAIL(ObMultipleSkipScanMerge::open(ranges_->at(cur_range_idx_), skip_scan_ranges_->at(cur_range_idx_)))) {
STORAGE_LOG(WARN, "Fail to open cur range", K(ret), K(cur_range_idx_));
}
}
}
} else {
break;
}
}
return ret;
}
}
}

View File

@ -0,0 +1,46 @@
// Copyright (c) 2021 OceanBase
// OceanBase 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.
#ifndef OCEANBASE_STORAGE_MULTIPLE_MULTI_SKIP_SCAN_MERGE_H
#define OCEANBASE_STORAGE_MULTIPLE_MULTI_SKIP_SCAN_MERGE_H
#include "ob_multiple_skip_scan_merge.h"
namespace oceanbase
{
namespace storage
{
class ObMultipleMultiSkipScanMerge final : public ObMultipleSkipScanMerge
{
public:
ObMultipleMultiSkipScanMerge();
virtual ~ObMultipleMultiSkipScanMerge();
virtual int init(
const ObTableAccessParam &param,
ObTableAccessContext &context,
const ObGetTableParam &get_table_param) override;
virtual void reset() override;
virtual void reuse() override;
int open(
const common::ObIArray<blocksstable::ObDatumRange> &ranges,
const common::ObIArray<blocksstable::ObDatumRange> &skip_scan_ranges);
protected:
virtual int inner_get_next_row(blocksstable::ObDatumRow &row) override;
virtual int inner_get_next_rows() override;
private:
int64_t cur_range_idx_;
const ObIArray<blocksstable::ObDatumRange> *ranges_;
const ObIArray<blocksstable::ObDatumRange> *skip_scan_ranges_;
};
}
}
#endif // OCEANBASE_STORAGE_MULTIPLE_MULTI_SKIP_SCAN_MERGE_H

View File

@ -200,7 +200,6 @@ int ObMultipleScanMerge::construct_iters()
void ObMultipleScanMerge::reset()
{
ObMultipleMerge::reset();
if (nullptr != access_ctx_ && nullptr != access_ctx_->stmt_allocator_) {
if (nullptr != simple_merge_) {
simple_merge_->~ObScanSimpleMerger();
@ -219,6 +218,7 @@ void ObMultipleScanMerge::reset()
consumer_cnt_ = 0;
range_ = NULL;
cow_range_.reset();
ObMultipleMerge::reset();
}
void ObMultipleScanMerge::reuse()

View File

@ -0,0 +1,442 @@
// Copyright (c) 2021 OceanBase
// OceanBase 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.
#include "ob_multiple_skip_scan_merge.h"
#include "lib/oblog/ob_log_module.h"
namespace oceanbase
{
namespace storage
{
ObMultipleSkipScanMerge::ObMultipleSkipScanMerge()
: ObMultipleScanMerge(),
state_(SCAN_ROWKEY),
schema_rowkey_cnt_(0),
ss_rowkey_prefix_cnt_(0),
scan_rowkey_range_(),
scan_rows_range_(),
datums_cnt_(0),
datums_(nullptr),
range_allocator_("SKIP_SCAN")
{
}
ObMultipleSkipScanMerge::~ObMultipleSkipScanMerge()
{
reset();
}
int ObMultipleSkipScanMerge::init(
const ObTableAccessParam &param,
ObTableAccessContext &context,
const ObGetTableParam &get_table_param)
{
int ret = OB_SUCCESS;
context.range_allocator_ = &range_allocator_;
if (OB_FAIL(ObMultipleScanMerge::init(param, context, get_table_param))) {
STORAGE_LOG(WARN, "Fail to init ObMultipleScanMerge", K(ret), K(param), K(context), K(get_table_param));
} else {
// prepare ranges for finding distinct rowkey prefix and outputing rows
void *buf = nullptr;
schema_rowkey_cnt_ = param.iter_param_.get_schema_rowkey_count();
ss_rowkey_prefix_cnt_ = param.iter_param_.get_ss_rowkey_prefix_cnt();
datums_cnt_ = SKIP_SCAN_ROWKEY_DATUMS_ARRAY_CNT * schema_rowkey_cnt_;
if (schema_rowkey_cnt_ <= 0 || ss_rowkey_prefix_cnt_ <= 0 || ss_rowkey_prefix_cnt_ > schema_rowkey_cnt_) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument", K(ret), K(schema_rowkey_cnt_), K(ss_rowkey_prefix_cnt_));
} else if (OB_ISNULL(buf = context.stmt_allocator_->alloc(sizeof(ObStorageDatum) * datums_cnt_))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "Fail to alloc datums", K(ret), K(datums_cnt_));
} else if (FALSE_IT(datums_ = new (buf) ObStorageDatum[datums_cnt_])) {
} else if (OB_FAIL(prepare_range(start_key_of_scan_rowkey_range(), scan_rowkey_range_))) {
STORAGE_LOG(WARN, "Fail to prepare distinct scan range", K(ret));
} else if (OB_FAIL(prepare_range(start_key_of_scan_rows_range(), scan_rows_range_))) {
STORAGE_LOG(WARN, "Fail to prepare skip scan range", K(ret));
} else {
STORAGE_LOG(DEBUG, "success to init ObMultipleSkipScanMerge", K(param), K(context), K(get_table_param),
K(schema_rowkey_cnt_), K(ss_rowkey_prefix_cnt_));
}
}
return ret;
}
void ObMultipleSkipScanMerge::reset()
{
state_ = SCAN_ROWKEY;
schema_rowkey_cnt_ = 0;
ss_rowkey_prefix_cnt_ = 0;
scan_rowkey_range_.reset();
scan_rows_range_.reset();
datums_cnt_ = 0;
if (OB_NOT_NULL(datums_) && OB_NOT_NULL(access_ctx_->stmt_allocator_)) {
access_ctx_->stmt_allocator_->free(datums_);
}
datums_ = nullptr;
range_allocator_.reset();
ObMultipleScanMerge::reset();
}
void ObMultipleSkipScanMerge::reuse()
{
state_ = SCAN_ROWKEY;
reuse_datums();
range_allocator_.reuse();
ObMultipleScanMerge::reuse();
}
// range: the original key range to scan rows
// skip_scan_range: the key range only contains suffix columns in rowkey
int ObMultipleSkipScanMerge::open(const blocksstable::ObDatumRange &range, const blocksstable::ObDatumRange &skip_scan_range)
{
int ret = OB_SUCCESS;
bool exceeded = false;
const int64_t skip_range_datum_cnt = schema_rowkey_cnt_ - ss_rowkey_prefix_cnt_;
if (skip_scan_range.is_whole_range()) {
ret = OB_NOT_SUPPORTED;
STORAGE_LOG(WARN, "not supported index skip scan plan", K(ret));
} else if (skip_scan_range.start_key_.get_datum_cnt() > skip_range_datum_cnt ||
(!skip_scan_range.start_key_.is_min_rowkey() && skip_scan_range.start_key_.get_datum_cnt() != skip_range_datum_cnt) ||
(!skip_scan_range.end_key_.is_max_rowkey() && skip_scan_range.end_key_.get_datum_cnt() != skip_range_datum_cnt)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid skip scan range", K(ret), K(skip_scan_range), K(schema_rowkey_cnt_), K(ss_rowkey_prefix_cnt_));
} else if (OB_FAIL(ObMultipleScanMerge::open(range))) {
STORAGE_LOG(WARN, "Fail to open ObMultipleScanMerge", K(ret), K(range));
} else {
prepare_rowkey(start_key_of_scan_rowkey_range(), range.start_key_, schema_rowkey_cnt_, true);
prepare_rowkey(end_key_of_scan_rowkey_range(), range.end_key_, schema_rowkey_cnt_, false);
scan_rowkey_range_.set_border_flag(range.get_border_flag());
// generate key range for outputing rows
for (int64_t i = 0; i < ss_rowkey_prefix_cnt_; ++i) {
start_key_of_scan_rows_range()[i].set_min();
end_key_of_scan_rows_range()[i].set_max();
}
prepare_rowkey(start_key_of_scan_rows_range() + ss_rowkey_prefix_cnt_,
skip_scan_range.start_key_,
schema_rowkey_cnt_ - ss_rowkey_prefix_cnt_,
true);
prepare_rowkey(end_key_of_scan_rows_range() + ss_rowkey_prefix_cnt_,
skip_scan_range.end_key_,
schema_rowkey_cnt_ - ss_rowkey_prefix_cnt_,
false);
scan_rows_range_.set_border_flag(skip_scan_range.get_border_flag());
STORAGE_LOG(TRACE, "open skip scan", K(schema_rowkey_cnt_), K(ss_rowkey_prefix_cnt_),
K(scan_rows_range_), K(range), K(skip_scan_range));
}
return ret;
}
int ObMultipleSkipScanMerge::inner_get_next_row(blocksstable::ObDatumRow &row)
{
int ret = OB_SUCCESS;
bool got_row = false;
while (OB_SUCC(ret) && !got_row) {
switch(state_) {
case SCAN_ROWKEY: {
// get next rowkey
// after get next rowkey, update and open scan rows range
if (OB_FAIL(ObMultipleScanMerge::inner_get_next_row(row))) {
if (OB_UNLIKELY(OB_ITER_END != ret && OB_PUSHDOWN_STATUS_CHANGED != ret)) {
STORAGE_LOG(WARN, "Fail to get next row", K(ret));
} else if (OB_PUSHDOWN_STATUS_CHANGED == ret) {
} else {
state_ = SCAN_FINISHED;
}
} else {
state_ = UPDATE_SCAN_ROWS_RANGE;
}
break;
}
case UPDATE_SCAN_ROWS_RANGE: {
if (OB_FAIL(update_scan_rows_range(row))) {
if (OB_LIKELY(OB_ITER_END == ret)) {
ret = OB_SUCCESS;
state_ = UPDATE_SCAN_ROWKEY_RANGE;
} else {
STORAGE_LOG(WARN, "Fail to update scan rows range", K(ret), K(row));
}
} else {
STORAGE_LOG(DEBUG, "skip scan update scan rows range", K(row), K(scan_rows_range_));
state_ = SCAN_ROWS;
}
break;
}
case SCAN_ROWS: {
// get next row
// after get next row, update and open scan rowkey range
if (OB_FAIL(ObMultipleScanMerge::inner_get_next_row(row))) {
if (OB_UNLIKELY(OB_ITER_END != ret && OB_PUSHDOWN_STATUS_CHANGED != ret)) {
STORAGE_LOG(WARN, "Fail to get next row", K(ret));
} else if (OB_PUSHDOWN_STATUS_CHANGED == ret) {
} else {
ret = OB_SUCCESS;
state_ = UPDATE_SCAN_ROWKEY_RANGE;
}
} else {
STORAGE_LOG(DEBUG, "skip scan get next row", K(row));
got_row = true;
}
break;
}
case UPDATE_SCAN_ROWKEY_RANGE: {
if (OB_FAIL(update_scan_rowkey_range())) {
if (OB_UNLIKELY(OB_ITER_END != ret)) {
STORAGE_LOG(WARN, "Fail to update scan rowkey range", K(ret), K(row));
} else {
state_ = SCAN_FINISHED;
}
} else {
STORAGE_LOG(DEBUG, "skip scan update scan rowkey range", K(row), K(scan_rowkey_range_));
state_ = SCAN_ROWKEY;
}
break;
}
case SCAN_FINISHED: {
ret = OB_ITER_END;
break;
}
default : {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected state", K(state_));
}
}
}
return ret;
}
int ObMultipleSkipScanMerge::inner_get_next_rows()
{
int ret = OB_SUCCESS;
bool end_loop = false;
if (SCAN_ROWS != state_) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected state", K(ret), K(state_));
} else {
while (OB_SUCC(ret) && !end_loop) {
switch(state_) {
case SCAN_ROWKEY: {
if (OB_FAIL(ObMultipleScanMerge::inner_get_next_row(unprojected_row_))) {
if (OB_UNLIKELY(OB_ITER_END != ret && OB_PUSHDOWN_STATUS_CHANGED != ret)) {
STORAGE_LOG(WARN, "Fail to get next row", K(ret));
} else if (OB_PUSHDOWN_STATUS_CHANGED == ret) {
} else {
state_ = SCAN_FINISHED;
}
} else {
state_ = UPDATE_SCAN_ROWS_RANGE;
}
break;
}
case UPDATE_SCAN_ROWS_RANGE: {
if (OB_FAIL(update_scan_rows_range(unprojected_row_))) {
if (OB_LIKELY(OB_ITER_END == ret)) {
ret = OB_SUCCESS;
state_ = UPDATE_SCAN_ROWKEY_RANGE;
} else {
STORAGE_LOG(WARN, "Fail to update scan rows range", K(ret), K(unprojected_row_));
}
} else {
STORAGE_LOG(DEBUG, "skip scan update scan rows range", K(unprojected_row_), K(scan_rows_range_));
state_ = SCAN_ROWS;
}
break;
}
case SCAN_ROWS: {
bool can_batch = false;
if (OB_FAIL(can_batch_scan(can_batch))) {
STORAGE_LOG(WARN, "Fail to check can batch scan", K(ret));
} else if (!can_batch) {
end_loop = true;
ret = OB_PUSHDOWN_STATUS_CHANGED;
} else if (OB_FAIL(ObMultipleScanMerge::inner_get_next_rows())) {
if (OB_UNLIKELY(OB_ITER_END != ret && OB_PUSHDOWN_STATUS_CHANGED != ret)) {
STORAGE_LOG(WARN, "Fail to get next rows", K(ret));
} else if (OB_PUSHDOWN_STATUS_CHANGED == ret) {
} else {
ret = OB_SUCCESS;
state_ = UPDATE_SCAN_ROWKEY_RANGE;
}
} else {
end_loop = true;
}
break;
}
case UPDATE_SCAN_ROWKEY_RANGE: {
if (OB_FAIL(update_scan_rowkey_range())) {
if (OB_UNLIKELY(OB_ITER_END != ret)) {
STORAGE_LOG(WARN, "Fail to update scan rowkey range", K(ret), K(unprojected_row_));
} else {
state_ = SCAN_FINISHED;
}
} else {
STORAGE_LOG(DEBUG, "skip scan update scan rowkey range", K(unprojected_row_), K(scan_rowkey_range_));
state_ = SCAN_ROWKEY;
}
break;
}
case SCAN_FINISHED: {
ret = OB_ITER_END;
break;
}
default : {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected state", K(state_));
}
}
}
}
return ret;
}
int ObMultipleSkipScanMerge::can_batch_scan(bool &can_batch)
{
int ret = OB_SUCCESS;
can_batch = (state_ == SCAN_ROWS);
if (can_batch && OB_FAIL(ObMultipleScanMerge::can_batch_scan(can_batch))) {
STORAGE_LOG(WARN, "Fail to check can batch scan", K(ret));
}
return ret;
}
int ObMultipleSkipScanMerge::prepare_range(ObStorageDatum *datums, ObDatumRange &range)
{
int ret = OB_SUCCESS;
if (OB_FAIL(range.start_key_.assign(datums, schema_rowkey_cnt_))) {
STORAGE_LOG(WARN, "Fail to assign start key", K(ret), K(schema_rowkey_cnt_));
} else if (OB_FAIL(range.end_key_.assign(datums + schema_rowkey_cnt_, schema_rowkey_cnt_))) {
STORAGE_LOG(WARN, "Fail to assign end key", K(ret), K(schema_rowkey_cnt_));
}
return ret;
}
void ObMultipleSkipScanMerge::prepare_rowkey(
blocksstable::ObStorageDatum *datums,
const blocksstable::ObDatumRowkey &rowkey,
const int64_t datum_cnt,
const bool is_min)
{
for (int64_t i = 0; i < datum_cnt; ++i) {
if (i < rowkey.get_datum_cnt()) {
datums[i] = rowkey.get_datum(i);
} else if (is_min) {
datums[i].set_min();
} else {
datums[i].set_max();
}
}
}
int ObMultipleSkipScanMerge::update_scan_rows_range(blocksstable::ObDatumRow &row)
{
int ret = OB_SUCCESS;
range_allocator_.reuse();
for (int64_t i = 0; OB_SUCC(ret) && i < ss_rowkey_prefix_cnt_; ++i) {
ObStorageDatum &prefix_of_start_key = start_key_of_scan_rows_range()[i];
ObStorageDatum &prefix_of_end_key = end_key_of_scan_rows_range()[i];
prefix_of_start_key.reuse();
prefix_of_end_key.reuse();
if (OB_FAIL(prefix_of_start_key.deep_copy(row.storage_datums_[i], range_allocator_))) {
STORAGE_LOG(WARN, "Fail to deep copy start key's datum", K(ret), K(i), K(row), K(scan_rows_range_));
} else if (OB_FAIL(prefix_of_end_key.deep_copy(row.storage_datums_[i], range_allocator_))) {
STORAGE_LOG(WARN, "Fail to deep copy end key's datum", K(ret), K(i), K(row), K(scan_rows_range_));
}
}
if (OB_SUCC(ret)) {
// check current skip scan range may exceed original range?
// one case is in parallel execution, splitted range
bool exceeded = false;
if (OB_FAIL(check_range_exceeded(exceeded))) {
STORAGE_LOG(WARN, "Fail to check range exceed", K(ret));
} else if (exceeded) {
ret = OB_ITER_END;
}
}
if (OB_SUCC(ret)) {
ObMultipleScanMerge::reuse();
const ObColDescIArray *col_descs = nullptr;
if (OB_ISNULL(col_descs = access_param_->iter_param_.get_out_col_descs())) {
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(WARN, "Unexpected null out cols", K(ret));
} else if (OB_FAIL(scan_rows_range_.prepare_memtable_readable(*col_descs, range_allocator_))) {
STORAGE_LOG(WARN, "Fail to transfer store rowkey", K(ret), K(scan_rows_range_));
} else if (OB_FAIL(ObMultipleScanMerge::open(scan_rows_range_))) {
STORAGE_LOG(WARN, "Fail to open scan rows range", K(ret), K(scan_rows_range_));
}
}
STORAGE_LOG(TRACE, "Update and open scan rows range", K(ret), K(row), K(scan_rows_range_));
return ret;
}
int ObMultipleSkipScanMerge::update_scan_rowkey_range()
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!scan_rows_range_.is_valid())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected scan rows range", K(ret), K(scan_rows_range_));
} else {
ObStorageDatum *rowkey_datums = access_ctx_->query_flag_.is_reverse_scan() ?
end_key_of_scan_rowkey_range() :
start_key_of_scan_rowkey_range();
for (int64_t i = 0; OB_SUCC(ret) && i < ss_rowkey_prefix_cnt_; ++i) {
if (OB_FAIL(rowkey_datums[i].deep_copy(scan_rows_range_.start_key_.get_datum(i), range_allocator_))) {
STORAGE_LOG(WARN, "Fail to deep copy start key's datum", K(ret), K(i), K(scan_rowkey_range_));
}
}
if (OB_SUCC(ret)) {
for (int64_t i = ss_rowkey_prefix_cnt_; i < schema_rowkey_cnt_; ++i) {
access_ctx_->query_flag_.is_reverse_scan() ? rowkey_datums[i].set_min() : rowkey_datums[i].set_max();
}
access_ctx_->query_flag_.is_reverse_scan() ? scan_rowkey_range_.set_right_open() : scan_rowkey_range_.set_left_open();
int cmp_ret = 0;
const ObStorageDatumUtils &datum_utils = access_param_->iter_param_.get_read_info()->get_datum_utils();
if (OB_FAIL(scan_rowkey_range_.start_key_.compare(scan_rowkey_range_.end_key_, datum_utils, cmp_ret))) {
STORAGE_LOG(WARN, "Fail to compare", K(ret), K(scan_rowkey_range_));
} else if (cmp_ret >= 0) {
ret = OB_ITER_END;
} else {
ObMultipleScanMerge::reuse();
const ObColDescIArray *col_descs = nullptr;
if (OB_ISNULL(col_descs = access_param_->iter_param_.get_out_col_descs())) {
ret = OB_ERR_UNEXPECTED;
TRANS_LOG(WARN, "Unexpected null out cols", K(ret));
} else if (OB_FAIL(scan_rowkey_range_.prepare_memtable_readable(*col_descs, range_allocator_))) {
STORAGE_LOG(WARN, "Fail to transfer store rowkey", K(ret), K(scan_rowkey_range_));
} else if (OB_FAIL(ObMultipleScanMerge::open(scan_rowkey_range_))) {
STORAGE_LOG(WARN, "Fail to open scan rowkey range", K(ret), K(scan_rowkey_range_));
}
}
}
}
STORAGE_LOG(TRACE, "Update and open scan rowkey range", K(ret), K(scan_rows_range_), K(scan_rowkey_range_));
return ret;
}
int ObMultipleSkipScanMerge::check_range_exceeded(bool &exceeded)
{
int ret = OB_SUCCESS;
int cmp_ret = 0;
exceeded = false;
const ObStorageDatumUtils &datum_utils = access_param_->iter_param_.get_read_info()->get_datum_utils();
if (OB_FAIL(scan_rows_range_.end_key_.compare(scan_rowkey_range_.start_key_, datum_utils, cmp_ret))) {
STORAGE_LOG(WARN, "Fail to compare", K(ret), K(scan_rows_range_.end_key_), K(scan_rowkey_range_.start_key_));
} else if (cmp_ret < 0 || (0 == cmp_ret && (scan_rows_range_.is_right_open() || scan_rowkey_range_.is_left_open()))) {
exceeded = true;
} else if (OB_FAIL(scan_rows_range_.start_key_.compare(scan_rowkey_range_.end_key_, datum_utils, cmp_ret))) {
STORAGE_LOG(WARN, "Fail to compare", K(ret), K(scan_rows_range_.end_key_), K(scan_rowkey_range_.start_key_));
} else if (cmp_ret > 0 || (0 == cmp_ret && (scan_rows_range_.is_left_open() || scan_rowkey_range_.is_right_open()))) {
exceeded = true;
}
return ret;
}
}
}

View File

@ -0,0 +1,89 @@
// Copyright (c) 2021 OceanBase
// OceanBase 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.
#ifndef OCEANBASE_STORAGE_MULTIPLE_SKIP_SCAN_MERGE_
#define OCEANBASE_STORAGE_MULTIPLE_SKIP_SCAN_MERGE_
#include "ob_multiple_scan_merge.h"
#include "storage/blocksstable/ob_datum_row.h"
namespace oceanbase
{
namespace storage
{
using namespace oceanbase::blocksstable;
class ObMultipleSkipScanMerge : public ObMultipleScanMerge
{
public:
ObMultipleSkipScanMerge();
virtual ~ObMultipleSkipScanMerge();
virtual int init(
const ObTableAccessParam &param,
ObTableAccessContext &context,
const ObGetTableParam &get_table_param) override;
virtual void reset() override;
virtual void reuse() override;
int open(const blocksstable::ObDatumRange &range) { return OB_NOT_SUPPORTED; }
int open(const blocksstable::ObDatumRange &range, const blocksstable::ObDatumRange &skip_scan_range);
protected:
virtual int inner_get_next_row(blocksstable::ObDatumRow &row) override;
virtual int inner_get_next_rows() override;
virtual int can_batch_scan(bool &can_batch) override;
private:
const static int32_t START_KEY_OFFSET_OF_SCAN_ROWKEY_RANGE = 0;
const static int32_t END_KEY_OFFSET_OF_SCAN_ROWKEY_RANGE = 1;
const static int32_t START_KEY_OFFSET_OF_SCAN_ROWS_RANGE = 2;
const static int32_t END_KEY_OFFSET_OF_SCAN_ROWS_RANGE = 3;
const static int32_t SKIP_SCAN_ROWKEY_DATUMS_ARRAY_CNT = 4;
int prepare_range(blocksstable::ObStorageDatum *datums, blocksstable::ObDatumRange &range);
void prepare_rowkey(blocksstable::ObStorageDatum *datums, const blocksstable::ObDatumRowkey &rowkey,
const int64_t datum_cnt, const bool is_min);
int update_scan_rowkey_range();
int update_scan_rows_range(blocksstable::ObDatumRow &row);
int check_range_exceeded(bool &exceeded);
OB_INLINE blocksstable::ObStorageDatum* start_key_of_scan_rowkey_range()
{ return datums_ + START_KEY_OFFSET_OF_SCAN_ROWKEY_RANGE * schema_rowkey_cnt_; }
OB_INLINE blocksstable::ObStorageDatum* end_key_of_scan_rowkey_range()
{ return datums_ + END_KEY_OFFSET_OF_SCAN_ROWKEY_RANGE * schema_rowkey_cnt_; }
OB_INLINE blocksstable::ObStorageDatum* start_key_of_scan_rows_range()
{ return datums_ + START_KEY_OFFSET_OF_SCAN_ROWS_RANGE * schema_rowkey_cnt_; }
OB_INLINE blocksstable::ObStorageDatum* end_key_of_scan_rows_range()
{ return datums_ + END_KEY_OFFSET_OF_SCAN_ROWS_RANGE * schema_rowkey_cnt_; }
OB_INLINE void reuse_datums()
{
if (OB_NOT_NULL(datums_)) {
for (int64_t i = 0; i < datums_cnt_; ++i) {
datums_[i].reuse();
}
}
}
enum SkipScanState {
SCAN_ROWKEY,
UPDATE_SCAN_ROWS_RANGE,
SCAN_ROWS,
UPDATE_SCAN_ROWKEY_RANGE,
SCAN_FINISHED,
};
SkipScanState state_;
int64_t schema_rowkey_cnt_;
int64_t ss_rowkey_prefix_cnt_;
blocksstable::ObDatumRange scan_rowkey_range_;
blocksstable::ObDatumRange scan_rows_range_;
int64_t datums_cnt_;
blocksstable::ObStorageDatum *datums_;
common::ObArenaAllocator range_allocator_;
};
}
}
#endif // OCEANBASE_STORAGE_MULTIPLE_SKIP_SCAN_MERGE_

View File

@ -26,7 +26,7 @@ namespace storage
{
ObSingleMerge::ObSingleMerge()
: rowkey_(NULL), fuse_row_cache_fetcher_()
: rowkey_(NULL), full_row_(), handle_(), fuse_row_cache_fetcher_()
{
type_ = ObQRIterType::T_SINGLE_GET;
}
@ -46,7 +46,15 @@ int ObSingleMerge::open(const ObDatumRowkey &rowkey)
LOG_WARN("ObSingleMerge has not been inited", K(ret), K_(get_table_param));
} else {
const ObTabletMeta &tablet_meta = get_table_param_.tablet_iter_.tablet_handle_.get_obj()->get_tablet_meta();
if (OB_FAIL(fuse_row_cache_fetcher_.init(access_param_->iter_param_.tablet_id_, access_param_->iter_param_.get_read_info(), tablet_meta.clog_checkpoint_scn_.get_val_for_tx()))) {
if (!full_row_.is_valid()) {
if (OB_FAIL(full_row_.init(*access_ctx_->stmt_allocator_, access_param_->get_max_out_col_cnt()))) {
STORAGE_LOG(WARN, "Failed to init datum row", K(ret));
} else {
full_row_.count_ = access_param_->get_max_out_col_cnt();
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(fuse_row_cache_fetcher_.init(access_param_->iter_param_.tablet_id_, access_param_->iter_param_.get_read_info(), tablet_meta.clog_checkpoint_scn_.get_val_for_tx()))) {
STORAGE_LOG(WARN, "fail to init fuse row cache fetcher", K(ret));
} else {
rowkey_ = &rowkey;
@ -60,12 +68,14 @@ void ObSingleMerge::reset()
{
ObMultipleMerge::reset();
rowkey_ = nullptr;
full_row_.reset();
handle_.reset();
}
void ObSingleMerge::reuse()
{
ObMultipleMerge::reuse();
full_row_.row_flag_.reset();
rowkey_ = NULL;
handle_.reset();
}

View File

@ -46,11 +46,11 @@ private:
bool &final_result,
bool &have_uncommited_row,
bool &need_update_fuse_cache);
private:
const blocksstable::ObDatumRowkey *rowkey_;
blocksstable::ObFuseRowValueHandle handle_;
private:
static const int64_t SINGLE_GET_FUSE_ROW_CACHE_PUT_COUNT_THRESHOLD = 50;
const blocksstable::ObDatumRowkey *rowkey_;
blocksstable::ObDatumRow full_row_;
blocksstable::ObFuseRowValueHandle handle_;
ObFuseRowCacheFetcher fuse_row_cache_fetcher_;
// disallow copy
DISALLOW_COPY_AND_ASSIGN(ObSingleMerge);

View File

@ -73,12 +73,12 @@ int ObSSTableMultiVersionRowGetter::inner_open(
LOG_WARN("invalid argument", K(ret), KP(query_range), KP(table));
} else {
base_rowkey_ = static_cast<const ObDatumRowkey *>(query_range);
if (OB_FAIL(base_rowkey_->to_multi_version_range(*access_ctx.allocator_, multi_version_range_))) {
if (OB_FAIL(base_rowkey_->to_multi_version_range(*access_ctx.get_range_allocator(), multi_version_range_))) {
STORAGE_LOG(WARN, "Failed to transfer multi version range", K(ret), KPC_(base_rowkey));
} else if (OB_FAIL(ObSSTableRowScanner::inner_open(
iter_param, access_ctx, table, &multi_version_range_))) {
LOG_WARN("failed to open scanner", K(ret));
} else if (OB_FAIL(not_exist_row_.init(*access_ctx.allocator_, iter_param.get_out_col_cnt()))) {
} else if (OB_FAIL(not_exist_row_.init(*access_ctx.get_range_allocator(), iter_param.get_out_col_cnt()))) {
LOG_WARN("fail to init datum row", K(ret));
} else {
not_exist_row_.row_flag_.set_flag(ObDmlFlag::DF_NOT_EXIST);
@ -143,7 +143,7 @@ int ObSSTableMultiVersionRowScanner::inner_open(
ObSSTable *sstable = static_cast<ObSSTable *>(table);
base_range_ = static_cast<const ObDatumRange *>(query_range);
trans_version_range_ = access_ctx.trans_version_range_;
if (OB_FAIL(base_range_->to_multi_version_range(*access_ctx.allocator_, multi_version_range_))) {
if (OB_FAIL(base_range_->to_multi_version_range(*access_ctx.get_range_allocator(), multi_version_range_))) {
STORAGE_LOG(WARN, "Failed to transfer multi version range", K(ret), KPC(base_range_));
} else if (OB_FAIL(ObSSTableRowScanner::inner_open(iter_param, access_ctx, table, &multi_version_range_))) {
LOG_WARN("failed to open scanner", K(ret));
@ -192,7 +192,7 @@ int ObSSTableMultiVersionRowMultiGetter::inner_open(
ObDatumRange tmp_multi_version_range;
for (int i = 0; OB_SUCC(ret) && i < base_rowkeys_->count(); i++) {
tmp_multi_version_range.reset();
if (OB_FAIL(base_rowkeys_->at(i).to_multi_version_range(*access_ctx.allocator_, tmp_multi_version_range))) {
if (OB_FAIL(base_rowkeys_->at(i).to_multi_version_range(*access_ctx.get_range_allocator(), tmp_multi_version_range))) {
STORAGE_LOG(WARN, "Failed to transfer multi version range", K(ret), K(i), K(base_rowkeys_->at(i)));
} else if (OB_FAIL(multi_version_ranges_.push_back(tmp_multi_version_range))) {
LOG_WARN("push back multi version range failed", K(ret));
@ -202,7 +202,7 @@ int ObSSTableMultiVersionRowMultiGetter::inner_open(
} else if (OB_FAIL(ObSSTableRowMultiScanner::inner_open(
iter_param, access_ctx, table, &multi_version_ranges_))) {
LOG_WARN("failed to open multi scanner", K(ret));
} else if (OB_FAIL(not_exist_row_.init(*access_ctx.allocator_, iter_param.get_out_col_cnt()))) {
} else if (OB_FAIL(not_exist_row_.init(*access_ctx.get_range_allocator(), iter_param.get_out_col_cnt()))) {
LOG_WARN("fail to init datum row", K(ret));
} else {
not_exist_row_.row_flag_.set_flag(ObDmlFlag::DF_NOT_EXIST);
@ -303,7 +303,7 @@ int ObSSTableMultiVersionRowMultiScanner::inner_open(
ObDatumRange tmp_multi_version_range;
for (int i = 0; OB_SUCC(ret) && i < base_ranges->count(); i++) {
tmp_multi_version_range.reset();
if (OB_FAIL(base_ranges->at(i).to_multi_version_range(*access_ctx.allocator_, tmp_multi_version_range))) {
if (OB_FAIL(base_ranges->at(i).to_multi_version_range(*access_ctx.get_range_allocator(), tmp_multi_version_range))) {
STORAGE_LOG(WARN, "Failed to transfer multi version range", K(ret), K(i), K(base_ranges->at(i)));
} else if (OB_FAIL(multi_version_ranges_.push_back(tmp_multi_version_range))) {
LOG_WARN("push back multi version range failed", K(ret));

View File

@ -84,7 +84,6 @@ int ObSSTableRowMultiExister::exist_row(ObSSTableReadHandle &read_handle, ObDatu
}
if (OB_SUCC(ret)) {
store_row.scan_index_ = read_handle.range_idx_;
++prefetcher_.cur_range_fetch_idx_;
LOG_DEBUG("get exist row", K(read_handle.row_state_), K(*read_handle.rowkey_), KP(this));
}
return ret;
@ -93,59 +92,51 @@ int ObSSTableRowMultiExister::exist_row(ObSSTableReadHandle &read_handle, ObDatu
int ObSSTableRowMultiExister::exist_block_row(ObSSTableReadHandle &read_handle, ObDatumRow &store_row)
{
int ret = OB_SUCCESS;
if (-1 == read_handle.micro_begin_idx_) {
store_row.row_flag_.set_flag(ObDmlFlag::DF_NOT_EXIST);
} else if (read_handle.micro_begin_idx_ >= prefetcher_.micro_data_prefetch_idx_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpected reader micro idx", K(ret), K(prefetcher_), K(read_handle));
} else {
prefetcher_.cur_micro_data_fetch_idx_ = read_handle.micro_begin_idx_;
read_handle.micro_handle_ = &prefetcher_.current_micro_handle();
if (nullptr == micro_exister_) {
if (nullptr == (micro_exister_ = OB_NEWx(ObMicroBlockRowExister, access_ctx_->allocator_))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Fail to allocate micro exister, ", K(ret));
} else if (OB_FAIL(micro_exister_->init(*iter_param_, *access_ctx_, sstable_))) {
LOG_WARN("Fail to init micro exister, ", K(ret));
}
read_handle.micro_handle_ = &prefetcher_.current_micro_handle();
if (nullptr == micro_exister_) {
if (nullptr == (micro_exister_ = OB_NEWx(ObMicroBlockRowExister, access_ctx_->allocator_))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Fail to allocate micro exister, ", K(ret));
} else if (OB_FAIL(micro_exister_->init(*iter_param_, *access_ctx_, sstable_))) {
LOG_WARN("Fail to init micro exister, ", K(ret));
}
}
if (OB_SUCC(ret)) {
bool exist = false;
bool found = false;
ObMicroBlockData block_data;
if (OB_FAIL(read_handle.get_block_data(macro_block_reader_, block_data))) {
LOG_WARN("Fail to get block data", K(ret), K(read_handle));
} else if (OB_FAIL(micro_exister_->is_exist(
*read_handle.rowkey_,
block_data,
exist,
found))) {
LOG_WARN("Fail to get row", K(ret));
} else {
if (!found) {
store_row.row_flag_.set_flag(ObDmlFlag::DF_NOT_EXIST);
if (!access_ctx_->query_flag_.is_index_back() && access_ctx_->query_flag_.is_use_bloomfilter_cache() && !sstable_->is_small_sstable()) {
(void) OB_STORE_CACHE.get_bf_cache().inc_empty_read(
MTL_ID(),
iter_param_->table_id_,
read_handle.micro_handle_->macro_block_id_,
read_handle.rowkey_->get_datum_cnt());
if (read_handle.is_bf_contain_) {
++access_ctx_->table_store_stat_.bf_empty_read_cnt_;
}
if (OB_SUCC(ret)) {
bool exist = false;
bool found = false;
ObMicroBlockData block_data;
if (OB_FAIL(read_handle.get_block_data(macro_block_reader_, block_data))) {
LOG_WARN("Fail to get block data", K(ret), K(read_handle));
} else if (OB_FAIL(micro_exister_->is_exist(
*read_handle.rowkey_,
block_data,
exist,
found))) {
LOG_WARN("Fail to get row", K(ret));
} else {
if (!found) {
store_row.row_flag_.set_flag(ObDmlFlag::DF_NOT_EXIST);
if (!access_ctx_->query_flag_.is_index_back() && access_ctx_->query_flag_.is_use_bloomfilter_cache() && !sstable_->is_small_sstable()) {
(void) OB_STORE_CACHE.get_bf_cache().inc_empty_read(
MTL_ID(),
iter_param_->table_id_,
read_handle.micro_handle_->macro_block_id_,
read_handle.rowkey_->get_datum_cnt());
if (read_handle.is_bf_contain_) {
++access_ctx_->table_store_stat_.bf_empty_read_cnt_;
}
++access_ctx_->table_store_stat_.exist_row_.empty_read_cnt_;
EVENT_INC(ObStatEventIds::EXIST_ROW_EMPTY_READ);
} else {
if (exist) {
store_row.row_flag_.set_flag(ObDmlFlag::DF_UPDATE);
} else {
store_row.row_flag_.set_flag(ObDmlFlag::DF_DELETE);
}
++access_ctx_->table_store_stat_.exist_row_.effect_read_cnt_;
EVENT_INC(ObStatEventIds::EXIST_ROW_EFFECT_READ);
}
++access_ctx_->table_store_stat_.exist_row_.empty_read_cnt_;
EVENT_INC(ObStatEventIds::EXIST_ROW_EMPTY_READ);
} else {
if (exist) {
store_row.row_flag_.set_flag(ObDmlFlag::DF_UPDATE);
} else {
store_row.row_flag_.set_flag(ObDmlFlag::DF_DELETE);
}
++access_ctx_->table_store_stat_.exist_row_.effect_read_cnt_;
EVENT_INC(ObStatEventIds::EXIST_ROW_EFFECT_READ);
}
}
}

View File

@ -72,7 +72,7 @@ int ObSSTableRowMultiGetter::inner_open(
LOG_WARN("fail to switch context for prefetcher, ", K(ret));
}
if (OB_SUCC(ret)) {
if (OB_FAIL(prefetcher_.prefetch())) {
if (OB_FAIL(prefetcher_.multi_prefetch())) {
LOG_WARN("Fail to prefetch data", K(ret));
} else {
is_opened_ = true;
@ -94,29 +94,26 @@ int ObSSTableRowMultiGetter::inner_get_next_row(const blocksstable::ObDatumRow *
LOG_WARN("The ObSSTableRowMultiGetter has not been opened", K(ret), KP(this));
} else {
while (OB_SUCC(ret)) {
if (OB_FAIL(prefetcher_.prefetch())) {
LOG_WARN("Fail to prefetch micro block", K(ret));
} else if (prefetcher_.cur_range_fetch_idx_ >= prefetcher_.cur_range_prefetch_idx_) {
if (OB_LIKELY(prefetcher_.is_prefetch_end_)) {
if (OB_FAIL(prefetcher_.multi_prefetch())) {
LOG_WARN("Fail to prefetch micro block", K(ret), K_(prefetcher));
} else if (prefetcher_.fetch_rowkey_idx_ >= prefetcher_.prefetch_rowkey_idx_) {
if (OB_LIKELY(prefetcher_.is_prefetch_end())) {
ret = OB_ITER_END;
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Current fetch handle idx exceed prefetching idx", K(ret), K_(prefetcher));
}
} else if (!prefetcher_.is_prefetch_end_ &&
prefetcher_.cur_range_fetch_idx_ >= prefetcher_.prefetching_range_idx() &&
-1 == prefetcher_.current_read_handle().micro_begin_idx_) {
} else if (!prefetcher_.current_read_handle().cur_prefetch_end_) {
continue;
} else if (OB_FAIL(fetch_row(prefetcher_.current_read_handle(), store_row))) {
if (OB_LIKELY(OB_ITER_END == ret)) {
if (prefetcher_.cur_range_fetch_idx_ < prefetcher_.prefetching_range_idx() || prefetcher_.is_prefetch_end_) {
++prefetcher_.cur_range_fetch_idx_;
}
prefetcher_.mark_cur_rowkey_fetched(prefetcher_.current_read_handle());
ret = OB_SUCCESS;
} else {
LOG_WARN("Fail to fetch row", K(ret));
}
} else {
prefetcher_.mark_cur_rowkey_fetched(prefetcher_.current_read_handle());
break;
}
}
@ -145,20 +142,10 @@ int ObSSTableRowMultiGetter::fetch_row(ObSSTableReadHandle &read_handle, const b
} else if (OB_FAIL(micro_getter_->init(*iter_param_, *access_ctx_, sstable_))) {
LOG_WARN("Fail to init micro block row getter", K(ret));
}
//switch context each row due to the cache will be disabled if too many rows getted
} else if (OB_FAIL(micro_getter_->switch_context(*iter_param_, *access_ctx_, sstable_))) {
STORAGE_LOG(WARN, "Fail to switch context", K(ret));
}
if (OB_SUCC(ret) && ObSSTableRowState::IN_BLOCK == read_handle.row_state_) {
if (-1 == read_handle.micro_begin_idx_) {
read_handle.row_state_ = ObSSTableRowState::NOT_EXIST;
} else if (read_handle.micro_begin_idx_ >= prefetcher_.micro_data_prefetch_idx_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpected reader micro idx", K(ret), K(prefetcher_), K(read_handle));
} else {
prefetcher_.cur_micro_data_fetch_idx_ = read_handle.micro_begin_idx_;
read_handle.micro_handle_ = &prefetcher_.current_micro_handle();
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(micro_getter_->get_row(
@ -166,8 +153,6 @@ int ObSSTableRowMultiGetter::fetch_row(ObSSTableReadHandle &read_handle, const b
store_row,
macro_block_reader_))) {
LOG_WARN("Fail to get row", K(ret));
} else {
++prefetcher_.cur_range_fetch_idx_;
}
return ret;
}

View File

@ -51,7 +51,7 @@ protected:
ObSSTable *sstable_;
const ObTableIterParam *iter_param_;
ObTableAccessContext *access_ctx_;
ObIndexTreeMultiPassPrefetcher prefetcher_;
ObIndexTreeMultiPrefetcher prefetcher_;
ObMacroBlockReader macro_block_reader_;
private:
bool is_opened_;

View File

@ -60,6 +60,7 @@ ObTableAccessContext::ObTableAccessContext()
limit_param_(NULL),
stmt_allocator_(NULL),
allocator_(NULL),
range_allocator_(nullptr),
scan_mem_(nullptr),
table_scan_stat_(NULL),
table_store_stat_(),
@ -144,6 +145,7 @@ int ObTableAccessContext::init(ObTableScanParam &scan_param,
}
if (OB_SUCC(ret)) {
stmt_allocator_ = scan_param.allocator_;
range_allocator_ = nullptr;
ls_id_ = scan_param.ls_id_;
tablet_id_ = scan_param.tablet_id_;
query_flag_ = scan_param.scan_flag_;
@ -190,6 +192,7 @@ int ObTableAccessContext::init(const common::ObQueryFlag &query_flag,
timeout_ = ctx.timeout_;
allocator_ = &allocator;
stmt_allocator_ = &stmt_allocator;
range_allocator_ = nullptr;
trans_version_range_ = trans_version_range;
ls_id_ = ctx.ls_id_;
tablet_id_ = ctx.tablet_id_;
@ -217,6 +220,7 @@ int ObTableAccessContext::init(const common::ObQueryFlag &query_flag,
timeout_ = ctx.timeout_;
allocator_ = &allocator;
stmt_allocator_ = &allocator;
range_allocator_ = nullptr;
trans_version_range_ = trans_version_range;
ls_id_ = ctx.ls_id_;
tablet_id_ = ctx.tablet_id_;
@ -252,6 +256,7 @@ void ObTableAccessContext::reset()
scan_mem_ = NULL;
}
allocator_ = NULL;
range_allocator_ = nullptr;
table_scan_stat_ = NULL;
table_store_stat_.reset();
out_cnt_ = 0;
@ -284,6 +289,7 @@ void ObTableAccessContext::reuse()
scan_mem_->reuse_arena();
}
allocator_ = NULL;
range_allocator_ = nullptr;
table_scan_stat_ = NULL;
out_cnt_ = 0;
trans_version_range_.reset();

View File

@ -81,6 +81,9 @@ struct ObTableAccessContext
inline bool is_limit_end() const {
return (nullptr != limit_param_ && limit_param_->limit_ >= 0 && (out_cnt_ - limit_param_->offset_ >= limit_param_->limit_));
}
inline common::ObIAllocator *get_range_allocator() {
return nullptr == range_allocator_ ? allocator_ : range_allocator_;
}
// used for query
int init(ObTableScanParam &scan_param,
ObStoreCtx &ctx,
@ -107,6 +110,7 @@ struct ObTableAccessContext
KP_(limit_param),
KP_(stmt_allocator),
KP_(allocator),
KP_(range_allocator),
KP_(table_scan_stat),
K_(out_cnt),
K_(trans_version_range),
@ -135,6 +139,8 @@ public:
common::ObIAllocator *stmt_allocator_;
// storage scan/rescan interface level allocator, will be reclaimed in every scan/rescan call
common::ObIAllocator *allocator_;
// scan/rescan level alloctor in storage, will be reclaimed in every reuse/open call
common::ObIAllocator *range_allocator_;
lib::MemoryContext scan_mem_; // scan/rescan level memory entity, only for query
common::ObTableScanStatistic *table_scan_stat_;
ObTableStoreStat table_store_stat_;

View File

@ -39,6 +39,7 @@ ObTableIterParam::ObTableIterParam()
is_same_schema_column_(false),
vectorized_enabled_(false),
has_virtual_columns_(false),
ss_rowkey_prefix_cnt_(0),
pd_storage_flag_(0)
{
}
@ -62,6 +63,7 @@ void ObTableIterParam::reset()
is_same_schema_column_ = false;
pd_storage_flag_ = 0;
pushdown_filter_ = nullptr;
ss_rowkey_prefix_cnt_ = 0;
vectorized_enabled_ = false;
has_virtual_columns_ = false;
}
@ -221,6 +223,9 @@ int ObTableAccessParam::init(
if (OB_FAIL(iter_param_.check_read_info_valid())) {
STORAGE_LOG(WARN, "Failed to check read info valdie", K(ret), K(iter_param_));
} else if (scan_param.use_index_skip_scan() &&
OB_FAIL(get_prefix_cnt_for_skip_scan(scan_param, iter_param_))) {
STORAGE_LOG(WARN, "Failed to get prefix for skip scan", K(ret));
} else {
is_inited_ = true;
}
@ -229,6 +234,26 @@ int ObTableAccessParam::init(
return ret;
}
int ObTableAccessParam::get_prefix_cnt_for_skip_scan(const ObTableScanParam &scan_param, ObTableIterParam &iter_param)
{
int ret = OB_SUCCESS;
const int64_t key_range_count = scan_param.key_ranges_.count();
const int64_t skip_range_count = scan_param.ss_key_ranges_.count();
if (OB_UNLIKELY(key_range_count != skip_range_count)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(key_range_count), K(skip_range_count));
} else {
const int64_t prefix = iter_param.get_schema_rowkey_count() - scan_param.ss_key_ranges_.at(0).start_key_.length();
if (OB_UNLIKELY(prefix <= 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(prefix), K(scan_param.key_ranges_), K(scan_param.ss_key_ranges_));
} else {
iter_param.ss_rowkey_prefix_cnt_ = prefix;
}
}
return ret;
}
int ObTableAccessParam::init_merge_param(
const uint64_t table_id,
const common::ObTabletID &tablet_id,

View File

@ -127,6 +127,8 @@ public:
}
OB_INLINE bool need_fill_group_idx() const
{ return get_group_idx_col_index() != common::OB_INVALID_INDEX; }
OB_INLINE int64_t get_ss_rowkey_prefix_cnt() const
{ return ss_rowkey_prefix_cnt_; }
OB_INLINE void disable_blockscan()
{ pd_blockscan_ = 0; }
OB_INLINE bool enable_pd_blockscan() const
@ -156,6 +158,7 @@ public:
bool is_same_schema_column_;
bool vectorized_enabled_;
bool has_virtual_columns_;
int64_t ss_rowkey_prefix_cnt_;
union {
struct {
int32_t pd_blockscan_:1;
@ -187,6 +190,7 @@ public:
const ObTableReadInfo &full_read_info,
const share::schema::ObTableSchemaParam &schema_param,
const common::ObIArray<int32_t> *out_cols_project);
int get_prefix_cnt_for_skip_scan(const ObTableScanParam &scan_param, ObTableIterParam &iter_param);
// used for index back when query
OB_INLINE int64_t get_out_col_cnt() const { return iter_param_.get_out_col_cnt(); }
OB_INLINE int64_t get_max_out_col_cnt() const { return iter_param_.get_max_out_col_cnt(); }

View File

@ -46,6 +46,7 @@ ObTableScanIterator::ObTableScanIterator()
get_merge_(NULL),
scan_merge_(NULL),
multi_scan_merge_(NULL),
skip_scan_merge_(NULL),
row_sample_iterator_(NULL),
block_sample_iterator_(NULL),
main_table_param_(),
@ -66,30 +67,14 @@ ObTableScanIterator::~ObTableScanIterator()
void ObTableScanIterator::reset()
{
if (NULL != single_merge_) {
single_merge_->~ObSingleMerge();
single_merge_ = NULL;
}
if (NULL != get_merge_) {
get_merge_->~ObMultipleGetMerge();
get_merge_ = NULL;
}
if (NULL != scan_merge_) {
scan_merge_->~ObMultipleScanMerge();
scan_merge_ = NULL;
}
if (NULL != multi_scan_merge_) {
multi_scan_merge_->~ObMultipleMultiScanMerge();
multi_scan_merge_ = NULL;
}
if (NULL != row_sample_iterator_) {
row_sample_iterator_->~ObRowSampleIterator();
row_sample_iterator_ = NULL;
}
if (NULL != block_sample_iterator_) {
block_sample_iterator_->~ObBlockSampleIterator();
block_sample_iterator_ = NULL;
}
reset_scan_iter(single_merge_);
reset_scan_iter(get_merge_);
reset_scan_iter(scan_merge_);
reset_scan_iter(multi_scan_merge_);
reset_scan_iter(skip_scan_merge_);
reset_scan_iter(row_sample_iterator_);
reset_scan_iter(block_sample_iterator_);
main_table_param_.reset();
main_table_ctx_.reset();
get_table_param_.reset();
@ -101,26 +86,30 @@ void ObTableScanIterator::reset()
is_inited_ = false;
}
template<typename T>
void ObTableScanIterator::reset_scan_iter(T *&iter)
{
if (NULL != iter) {
iter->~T();
iter = NULL;
}
}
void ObTableScanIterator::reuse_row_iters()
{
if (NULL != single_merge_) {
single_merge_->reuse();
}
if (NULL != get_merge_) {
get_merge_->reuse();
}
if (NULL != scan_merge_) {
scan_merge_->reuse();
}
if (NULL != multi_scan_merge_) {
multi_scan_merge_->reuse();
}
if (NULL != row_sample_iterator_) {
row_sample_iterator_->reuse();
}
if (NULL != block_sample_iterator_) {
block_sample_iterator_->reuse();
}
#define REUSE_SCAN_ITER(iter) \
if (NULL != iter) { \
iter->reuse(); \
} \
REUSE_SCAN_ITER(single_merge_);
REUSE_SCAN_ITER(get_merge_);
REUSE_SCAN_ITER(scan_merge_);
REUSE_SCAN_ITER(multi_scan_merge_);
REUSE_SCAN_ITER(skip_scan_merge_);
REUSE_SCAN_ITER(row_sample_iterator_);
REUSE_SCAN_ITER(block_sample_iterator_);
#undef REUSE_SCAN_ITER
}
int ObTableScanIterator::prepare_table_param(const ObTabletHandle &tablet_handle)
@ -280,29 +269,22 @@ int ObTableScanIterator::switch_param(ObTableScanParam &scan_param, const ObTabl
int ObTableScanIterator::switch_param_for_iter()
{
#define SWITCH_PARAM_FOR_ITER(iter, ret) \
if (OB_SUCC(ret) && NULL != iter) { \
if (OB_FAIL(switch_scan_param(*iter))) { \
STORAGE_LOG(WARN, "Fail to switch param, ", K(ret), KP(iter), KPC(iter)); \
} \
} \
int ret = OB_SUCCESS;
get_table_param_.frozen_version_ = scan_param_->frozen_version_;
get_table_param_.sample_info_ = scan_param_->sample_info_;
if (NULL != single_merge_) {
if (OB_FAIL(switch_scan_param(*single_merge_))) {
STORAGE_LOG(WARN, "Fail to switch param for single merge, ", K(ret), KP_(single_merge), KPC_(single_merge));
}
}
if (OB_SUCC(ret) && NULL != get_merge_) {
if (OB_FAIL(switch_scan_param(*get_merge_))) {
STORAGE_LOG(WARN, "Fail to switch param for get merge, ", K(ret), KP_(get_merge), KPC_(get_merge));
}
}
if (OB_SUCC(ret) && NULL != scan_merge_) {
if (OB_FAIL(switch_scan_param(*scan_merge_))) {
STORAGE_LOG(WARN, "Fail to switch param for scan merge, ", K(ret), KP_(scan_merge), KPC_(scan_merge));
}
}
if (OB_SUCC(ret) && NULL != multi_scan_merge_) {
if (OB_FAIL(switch_scan_param(*multi_scan_merge_))) {
STORAGE_LOG(WARN, "Fail to switch param for multi scan merge, ", K(ret), KP_(multi_scan_merge), KPC_(multi_scan_merge));
}
}
SWITCH_PARAM_FOR_ITER(single_merge_, ret);
SWITCH_PARAM_FOR_ITER(get_merge_, ret);
SWITCH_PARAM_FOR_ITER(scan_merge_, ret);
SWITCH_PARAM_FOR_ITER(multi_scan_merge_, ret);
SWITCH_PARAM_FOR_ITER(skip_scan_merge_, ret);
#undef SWITCH_PARAM_FOR_ITER
return ret;
}
@ -349,6 +331,21 @@ do { \
} \
} while(0)
#define INIT_AND_OPEN_SKIP_SCAN_ITER(ITER_PTR, RANGE, SUFFIX_RANGE, USE_FUSE_CACHE) \
do { \
STORAGE_LOG(TRACE, "skip scan", K(main_table_param_), K(RANGE), K(SUFFIX_RANGE)); \
if (nullptr == ITER_PTR && OB_FAIL(init_scan_iter(ITER_PTR))) { \
STORAGE_LOG(WARN, "Failed to init single merge", K(ret)); \
} else { \
main_table_ctx_.use_fuse_row_cache_ = USE_FUSE_CACHE; \
if (OB_FAIL(ITER_PTR->open(RANGE, SUFFIX_RANGE))) { \
STORAGE_LOG(WARN, "Fail to open multiple merge iterator", K(ret)); \
} else { \
main_iter_ = ITER_PTR; \
} \
} \
} while(0)
int ObTableScanIterator::open_iter()
{
int ret = OB_SUCCESS;
@ -405,9 +402,14 @@ int ObTableScanIterator::open_iter()
main_table_ctx_.use_fuse_row_cache_ = false;
}
}
} else if (scan_param_->use_index_skip_scan()) {
INIT_AND_OPEN_SKIP_SCAN_ITER(skip_scan_merge_, table_scan_range_.get_ranges().at(0), table_scan_range_.get_suffix_ranges().at(0), false);
} else {
INIT_AND_OPEN_ITER(scan_merge_, table_scan_range_.get_ranges().at(0), false);
}
} else if (scan_param_->use_index_skip_scan()) {
ret = OB_NOT_SUPPORTED;
STORAGE_LOG(WARN, "multiple ranges are not supported in index skip scan now");
} else {
INIT_AND_OPEN_ITER(multi_scan_merge_, table_scan_range_.get_ranges(), false);
}
@ -451,6 +453,7 @@ int ObTableScanIterator::open_iter()
}
#undef INIT_AND_OPEN_ITER
#undef INIT_AND_OPEN_SKIP_SCAN_ITER
int ObTableScanIterator::can_retire_to_row_sample(bool &retire)
{
@ -510,7 +513,8 @@ int ObTableScanIterator::get_next_row(ObNewRow *&row)
if (OB_FAIL(main_iter_->get_next_row(store_row))) {
if (OB_ITER_END != ret) {
STORAGE_LOG(WARN, "Fail to get next row, ", K(ret), KPC_(scan_param), K_(main_table_param),
KP(single_merge_), KP(get_merge_), KP(scan_merge_), KP(multi_scan_merge_));
KP(single_merge_), KP(get_merge_), KP(scan_merge_), KP(multi_scan_merge_),
KP(skip_scan_merge_));
}
} else {
row = &(store_row->get_new_row());
@ -540,7 +544,8 @@ int ObTableScanIterator::get_next_rows(int64_t &count, int64_t capacity)
if (OB_FAIL(main_iter_->get_next_rows(count, capacity))) {
if (OB_ITER_END != ret) {
STORAGE_LOG(WARN, "Fail to get next row, ", K(ret), K(*scan_param_), K_(main_table_param),
KP(single_merge_), KP(get_merge_), KP(scan_merge_), KP(multi_scan_merge_));
KP(single_merge_), KP(get_merge_), KP(scan_merge_), KP(multi_scan_merge_),
KP(skip_scan_merge_));
}
}
}

View File

@ -26,6 +26,8 @@
#include "ob_multiple_merge.h"
#include "ob_multiple_multi_scan_merge.h"
#include "ob_multiple_scan_merge.h"
#include "ob_multiple_skip_scan_merge.h"
#include "ob_multiple_multi_skip_scan_merge.h"
#include "ob_row_sample_iterator.h"
#include "ob_single_merge.h"
#include "storage/tx_storage/ob_access_service.h"
@ -63,6 +65,7 @@ private:
int prepare_table_param(const ObTabletHandle &tablet_handle);
int prepare_table_context();
template<typename T> int init_scan_iter(T *&iter);
template<typename T> void reset_scan_iter(T *&iter);
int switch_scan_param(ObMultipleMerge &iter);
void reuse_row_iters();
int switch_param_for_iter();
@ -76,6 +79,7 @@ private:
ObMultipleGetMerge *get_merge_;
ObMultipleScanMerge *scan_merge_;
ObMultipleMultiScanMerge *multi_scan_merge_;
ObMultipleSkipScanMerge *skip_scan_merge_;
ObRowSampleIterator *row_sample_iterator_;
ObBlockSampleIterator *block_sample_iterator_; // TODO: refactor
// we should consider the constructor cost

View File

@ -23,6 +23,7 @@ namespace storage
ObTableScanRange::ObTableScanRange()
: rowkeys_(),
ranges_(),
skip_scan_ranges_(),
allocator_(nullptr),
status_(EMPTY),
is_inited_(false)
@ -30,16 +31,23 @@ ObTableScanRange::ObTableScanRange()
void ObTableScanRange::reset()
{
#define RESET_SCAN_RANGES(RANGES) \
do { \
for (int64_t i = 0; i < RANGES.count(); i++) { \
ObDatumRange &range = RANGES.at(i); \
if (!range.get_start_key().is_static_rowkey()) { \
allocator_->free(const_cast<ObStorageDatum *>(range.get_start_key().datums_)); \
} \
if (!range.get_end_key().is_static_rowkey()) { \
allocator_->free(const_cast<ObStorageDatum *>(range.get_end_key().datums_)); \
} \
} \
} while(0) \
if (nullptr != allocator_) {
for (int64_t i = 0; i < ranges_.count(); i++) {
ObDatumRange &range = ranges_.at(i);
if (!range.get_start_key().is_static_rowkey()) {
allocator_->free(const_cast<ObStorageDatum *>(range.get_start_key().datums_));
}
if (!range.get_end_key().is_static_rowkey()) {
allocator_->free(const_cast<ObStorageDatum *>(range.get_end_key().datums_));
}
}
RESET_SCAN_RANGES(ranges_);
RESET_SCAN_RANGES(skip_scan_ranges_);
for (int64_t i = 0; i < rowkeys_.count(); i++) {
if (!rowkeys_.at(i).is_static_rowkey()) {
allocator_->free(const_cast<ObStorageDatum *>(rowkeys_.at(i).datums_));
@ -48,6 +56,7 @@ void ObTableScanRange::reset()
}
rowkeys_.reset();
ranges_.reset();
skip_scan_ranges_.reset();
allocator_ = nullptr;
status_ = EMPTY;
is_inited_ = false;
@ -72,9 +81,16 @@ int ObTableScanRange::init(ObTableScanParam &scan_param)
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected error for invalid datum utils", K(ret), KPC(scan_param.table_param_));
} else if (scan_param.is_get_) {
if (OB_FAIL(init_rowkeys(scan_param.key_ranges_, scan_param.scan_flag_, datum_utils))) {
if (scan_param.use_index_skip_scan()) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected, index skip scan can only be used in scan", K(ret));
} else if (OB_FAIL(init_rowkeys(scan_param.key_ranges_, scan_param.scan_flag_, datum_utils))) {
STORAGE_LOG(WARN, "Failed to init rowkeys", K(ret));
}
} else if (scan_param.use_index_skip_scan()) {
if (OB_FAIL(init_ranges_in_skip_scan(scan_param.key_ranges_, scan_param.ss_key_ranges_, scan_param.scan_flag_, datum_utils))) {
STORAGE_LOG(WARN, "Failed to init range in skip scan", K(ret), K(scan_param.key_ranges_), K(scan_param.ss_key_ranges_));
}
} else if (OB_FAIL(init_ranges(scan_param.key_ranges_, scan_param.scan_flag_, datum_utils))) {
STORAGE_LOG(WARN, "Failed to init ranges", K(ret));
}
@ -239,6 +255,62 @@ int ObTableScanRange::init_ranges(const common::ObIArray<common::ObNewRange> &ra
return ret;
}
int ObTableScanRange::init_ranges_in_skip_scan(const common::ObIArray<common::ObNewRange> &ranges,
const common::ObIArray<common::ObNewRange> &skip_scan_ranges,
const common::ObQueryFlag &scan_flag,
const blocksstable::ObStorageDatumUtils *datum_utils)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(nullptr == allocator_ ||
ranges.count() != skip_scan_ranges.count()) ||
ranges.count() == 0) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument to init ranges", K(ret), K(allocator_), K(ranges.count()), K(skip_scan_ranges.count()));
} else {
common::ObSEArray<ObSkipScanWrappedRange, DEFAULT_RANGE_CNT> wrapped_ranges_;
const int64_t range_cnt = ranges.count();
for (int64_t i = 0; OB_SUCC(ret) && i < range_cnt; i++) {
ObSkipScanWrappedRange wrapped_range;
const ObNewRange &range = ranges.at(i);
const ObNewRange &skip_scan_range = skip_scan_ranges.at(i);
bool is_false = false;
if (OB_FAIL(always_false(range, is_false))) {
STORAGE_LOG(WARN, "Failed to check range always false", K(ret), K(range));
} else if (is_false) {
} else if (OB_FAIL(wrapped_range.datum_range_.from_range(range, *allocator_))) {
STORAGE_LOG(WARN, "Failed to transfer range to datum range", K(ret));
} else if (OB_FAIL(wrapped_range.datum_skip_range_.from_range(skip_scan_range, *allocator_))) {
STORAGE_LOG(WARN, "Failed to transfer skip range to datum range", K(ret));
} else if (OB_FAIL(wrapped_ranges_.push_back(wrapped_range))) {
STORAGE_LOG(WARN, "Failed to push back", K(ret), K(wrapped_range));
}
}
if (OB_SUCC(ret)) {
if (wrapped_ranges_.empty()) {
status_ = EMPTY;
} else if (wrapped_ranges_.count() > 1 && nullptr != datum_utils
&& (scan_flag.scan_order_ == ObQueryFlag::Forward || scan_flag.scan_order_ == ObQueryFlag::Reverse)) {
ObDatumComparor<ObSkipScanWrappedRange> comparor(*datum_utils, ret, scan_flag.is_reverse_scan());
std::sort(wrapped_ranges_.begin(), wrapped_ranges_.end(), comparor);
if (OB_FAIL(ret)) {
STORAGE_LOG(WARN, "Failed to sort datum ranges", K(ret), K(wrapped_ranges_));
}
}
}
if (OB_SUCC(ret) && EMPTY != status_) {
for (int64_t i = 0; OB_SUCC(ret) && i < wrapped_ranges_.count(); i++) {
const ObSkipScanWrappedRange &wrapped_range = wrapped_ranges_.at(i);
STORAGE_LOG(DEBUG, "skip scan range", K(wrapped_range));
if (OB_FAIL(ranges_.push_back(wrapped_range.datum_range_))) {
STORAGE_LOG(WARN, "Failed to push back datum range", K(ret));
} else if (OB_FAIL(skip_scan_ranges_.push_back(wrapped_range.datum_skip_range_))) {
STORAGE_LOG(WARN, "Failed to push back datum range", K(ret));
}
}
}
}
return ret;
}
} // namespace storage

View File

@ -37,6 +37,7 @@ public:
OB_INLINE bool is_empty() const { return EMPTY == status_; }
OB_INLINE void set_empty() { status_ = EMPTY; }
OB_INLINE const ObIArray<blocksstable::ObDatumRange> &get_ranges() const { return ranges_; }
OB_INLINE const ObIArray<blocksstable::ObDatumRange> &get_suffix_ranges() const { return skip_scan_ranges_; }
OB_INLINE const ObIArray<blocksstable::ObDatumRowkey> &get_rowkeys() const { return rowkeys_; }
TO_STRING_KV(K_(rowkeys), K_(ranges), K_(status), K_(is_inited));
private:
@ -44,10 +45,28 @@ private:
const common::ObQueryFlag &scan_flag,
const blocksstable::ObStorageDatumUtils *datum_utils);
int init_ranges(const common::ObIArray<common::ObNewRange> &ranges,
const common::ObQueryFlag &scan_flag,
const common::ObQueryFlag &scan_flag,
const blocksstable::ObStorageDatumUtils *datum_utils);
int init_ranges_in_skip_scan(const common::ObIArray<common::ObNewRange> &ranges,
const common::ObIArray<common::ObNewRange> &skip_scan_ranges,
const common::ObQueryFlag &scan_flag,
const blocksstable::ObStorageDatumUtils *datum_utils);
int always_false(const common::ObNewRange &range, bool &is_false);
private:
struct ObSkipScanWrappedRange
{
ObSkipScanWrappedRange() = default;
ObSkipScanWrappedRange(const blocksstable::ObDatumRange &datum_range, blocksstable::ObDatumRange &datum_skip_range)
: datum_range_(datum_range), datum_skip_range_(datum_skip_range)
{}
OB_INLINE int compare(const ObSkipScanWrappedRange &rhs, const blocksstable::ObStorageDatumUtils &datum_utils, int &cmp_ret) const
{
return datum_range_.compare(rhs.datum_range_, datum_utils, cmp_ret);
}
TO_STRING_KV(K_(datum_range), K_(datum_skip_range));
blocksstable::ObDatumRange datum_range_;
blocksstable::ObDatumRange datum_skip_range_;
};
enum RangeStatus
{
EMPTY,
@ -57,6 +76,7 @@ private:
static const int64_t DEFAULT_RANGE_CNT = 8;
common::ObSEArray<blocksstable::ObDatumRowkey, DEFAULT_RANGE_CNT> rowkeys_;
common::ObSEArray<blocksstable::ObDatumRange, DEFAULT_RANGE_CNT> ranges_;
common::ObSEArray<blocksstable::ObDatumRange, DEFAULT_RANGE_CNT> skip_scan_ranges_;
ObIAllocator *allocator_;
RangeStatus status_;
bool is_inited_;

View File

@ -56,12 +56,6 @@ void ObVectorStore::reset()
default_row_.reset();
}
void ObVectorStore::reuse()
{
ObBlockBatchedRowStore::reuse();
count_ = 0;
}
int ObVectorStore::init(const ObTableAccessParam &param)
{
int ret = OB_SUCCESS;

View File

@ -39,7 +39,6 @@ public:
virtual ~ObVectorStore();
virtual int init(const ObTableAccessParam &param) override;
virtual void reset() override;
virtual void reuse() override;
// shallow copy
virtual int fill_rows(
const int64_t group_idx,

View File

@ -2036,43 +2036,12 @@ int ObMicroBlockDecoder::get_rows(
LOG_WARN("invalid argument", K(ret), KP(row_ids), KP(cell_datas),
K(cols.count()), K(datums.count()));
} else {
common::ObObj cell;
for (int64_t i = 0; OB_SUCC(ret) && i < cols.count(); i++) {
int32_t col_id = cols.at(i);
if (OB_UNLIKELY(col_id >= header_->column_count_)) {
ret = OB_INDEX_OUT_OF_RANGE;
LOG_WARN("Vector store col id greate than store cnt", K(ret), K(header_->column_count_), K(col_id));
} else if (!decoders_[col_id].decoder_->can_vectorized()) {
// normal path
int64_t row_len = 0;
const char *row_data = NULL;
const int row_header_size = ObRowHeader::get_serialized_size();
int64_t row_id = common::OB_INVALID_INDEX;
common::ObDatum *col_datums = datums.at(i);
for (int64_t idx = 0; OB_SUCC(ret) && idx < row_cap; idx++) {
row_id = row_ids[idx];
if (OB_FAIL(row_index_->get(row_id, row_data, row_len))) {
LOG_WARN("get row data failed", K(ret), K(row_id));
} else {
ObBitStream bs(reinterpret_cast<unsigned char *>(const_cast<char *>(row_data)), row_len);
if (OB_FAIL(decoders_[col_id].decode(cell, row_id, bs, row_data, row_len))) {
LOG_WARN("Decode cell failed", K(ret));
} else if (OB_FAIL(col_datums[idx].from_obj(cell))) {
LOG_WARN("Failed to convert object from datum", K(ret), K(cell));
}
}
}
} else if (OB_FAIL(decoders_[col_id].batch_decode(
row_index_,
row_ids,
cell_datas,
row_cap,
datums.at(i)))) {
LOG_WARN("fail to get datums from decoder", K(ret), K(col_id), K(row_cap),
"row_ids", common::ObArrayWrap<const int64_t>(row_ids, row_cap));
}
if (OB_SUCC(ret) && nullptr != col_params.at(i)) {
common::ObDatum *col_datums = datums.at(i);
if (OB_FAIL(get_col_datums(col_id, row_ids, cell_datas, row_cap, col_datums))) {
LOG_WARN("Failed to get col datums", K(ret), K(i), K(col_id), K(row_cap));
} else if (nullptr != col_params.at(i)) {
// need padding
if (OB_FAIL(storage::pad_on_datums(
col_params.at(i)->get_accuracy(),
@ -2112,5 +2081,74 @@ int ObMicroBlockDecoder::get_row_count(
return ret;
}
int ObMicroBlockDecoder::get_min_or_max(
int32_t col_id,
const int64_t *row_ids,
const char **cell_datas,
const int64_t row_cap,
ObDatum *datum_buf,
ObMicroBlockAggInfo<ObDatum> &agg_info)
{
int ret = OB_SUCCESS;
decoder_allocator_.reuse();
if (OB_FAIL(get_col_datums(col_id, row_ids, cell_datas, row_cap, datum_buf))) {
LOG_WARN("Failed to get col datums", K(ret), K(col_id), K(row_cap));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < row_cap; ++i) {
if (datum_buf[i].is_nop()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected datum, can not process in batch", K(ret), K(i));
} else {
agg_info.update_min_or_max(datum_buf[i]);
LOG_DEBUG("update min/max", K(i), K(datum_buf[i]), K(agg_info));
}
}
}
return ret;
}
int ObMicroBlockDecoder::get_col_datums(
int32_t col_id,
const int64_t *row_ids,
const char **cell_datas,
const int64_t row_cap,
common::ObDatum *col_datums)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(col_id >= header_->column_count_)) {
ret = OB_INDEX_OUT_OF_RANGE;
LOG_WARN("Vector store col id greate than store cnt", K(ret), K(header_->column_count_), K(col_id));
} else if (!decoders_[col_id].decoder_->can_vectorized()) {
// normal path
common::ObObj cell;
int64_t row_len = 0;
const char *row_data = NULL;
const int row_header_size = ObRowHeader::get_serialized_size();
int64_t row_id = common::OB_INVALID_INDEX;
for (int64_t idx = 0; OB_SUCC(ret) && idx < row_cap; idx++) {
row_id = row_ids[idx];
if (OB_FAIL(row_index_->get(row_id, row_data, row_len))) {
LOG_WARN("get row data failed", K(ret), K(row_id));
} else {
ObBitStream bs(reinterpret_cast<unsigned char *>(const_cast<char *>(row_data)), row_len);
if (OB_FAIL(decoders_[col_id].decode(cell, row_id, bs, row_data, row_len))) {
LOG_WARN("Decode cell failed", K(ret));
} else if (OB_FAIL(col_datums[idx].from_obj(cell))) {
LOG_WARN("Failed to convert object from datum", K(ret), K(cell));
}
}
}
} else if (OB_FAIL(decoders_[col_id].batch_decode(
row_index_,
row_ids,
cell_datas,
row_cap,
col_datums))) {
LOG_WARN("fail to get datums from decoder", K(ret), K(col_id), K(row_cap),
"row_ids", common::ObArrayWrap<const int64_t>(row_ids, row_cap));
}
return ret;
}
}
}

View File

@ -260,6 +260,13 @@ public:
const int64_t row_cap,
const bool contains_null,
int64_t &count) override final;
int get_min_or_max(
int32_t col_id,
const int64_t *row_ids,
const char **cell_datas,
const int64_t row_cap,
ObDatum *datum_buf,
ObMicroBlockAggInfo<ObDatum> &agg_info);
virtual int64_t get_column_count() const override
{
OB_ASSERT(nullptr != header_);
@ -294,6 +301,12 @@ private:
const int64_t col_begin,
const int64_t col_end,
ObStorageDatum *datums);
int get_col_datums(int32_t col_id,
const int64_t *row_ids,
const char **cell_datas,
const int64_t row_cap,
common::ObDatum *col_datums);
//TODO @hanhui deleted after change rowkey to datum
int decode_cells(const uint64_t row_id,
const int64_t row_len,

View File

@ -619,7 +619,6 @@ int ObMicroBlockEncoder::build_block(char *&buf, int64_t &size)
if (OB_SUCC(ret)) {
header_->row_count_ = static_cast<uint32_t>(datum_rows_.count());
header_->encoding_has_out_row_column_ = has_out_row_column_;
const int64_t header_size = header_->header_size_;
char *data = data_buffer_.data() + header_size;
FOREACH(e, encoders_) {
@ -957,7 +956,6 @@ int ObMicroBlockEncoder::copy_and_append_row(const ObDatumRow &src, int64_t &sto
LOG_WARN("append row to array failed", K(ret), K(src));
}
}
return ret;
}

View File

@ -50,7 +50,9 @@ const int64_t BF_MICRO_BLOCK_HEADER_MAGIC = 1015;
const int64_t SERVER_SUPER_BLOCK_MAGIC = 1018;
const int64_t LINKED_MACRO_BLOCK_HEADER_MAGIC = 1019;
const int64_t MICRO_BLOCK_HEADER_VERSION = 1;
const int64_t MICRO_BLOCK_HEADER_VERSION_1 = 1;
const int64_t MICRO_BLOCK_HEADER_VERSION_2 = 2;
const int64_t MICRO_BLOCK_HEADER_VERSION = MICRO_BLOCK_HEADER_VERSION_2;
const int64_t LINKED_MACRO_BLOCK_HEADER_VERSION = 1;
const int64_t BF_MACRO_BLOCK_HEADER_VERSION = 1;
const int64_t BF_MICRO_BLOCK_HEADER_VERSION = 1;

View File

@ -59,6 +59,8 @@ public:
common::ObIAllocator &allocator,
common::ObStoreRange &store_range) const;
OB_INLINE int to_multi_version_range(common::ObIAllocator &allocator, ObDatumRange &dest) const;
OB_INLINE int prepare_memtable_readable(const common::ObIArray<share::schema::ObColDesc> &col_descs,
common::ObIAllocator &allocator);
// !!Attension only compare start key
OB_INLINE int compare(const ObDatumRange &rhs, const ObStorageDatumUtils &datum_utils, int &cmp_ret) const;
// maybe we will need serialize
@ -272,6 +274,18 @@ OB_INLINE int ObDatumRange::to_multi_version_range(common::ObIAllocator &allocat
return ret;
}
OB_INLINE int ObDatumRange::prepare_memtable_readable(const common::ObIArray<share::schema::ObColDesc> &col_descs,
common::ObIAllocator &allocator)
{
int ret = OB_SUCCESS;
if (OB_FAIL(start_key_.prepare_memtable_readable(col_descs, allocator))) {
STORAGE_LOG(WARN, "Failed to prepare start key", K(ret), K(start_key_), K(col_descs));
} else if (OB_FAIL(end_key_.prepare_memtable_readable(col_descs, allocator))) {
STORAGE_LOG(WARN, "Failed to prepare end key", K(ret), K(end_key_), K(col_descs));
}
return ret;
}
} // namespace blocksstable
} // namespace oceanbase
#endif

View File

@ -38,6 +38,7 @@ public:
OB_INLINE bool is_memtable_valid() const { return store_rowkey_.is_valid() && is_valid(); }
OB_INLINE int32_t get_datum_cnt() const { return datum_cnt_; }
OB_INLINE const ObStorageDatum *get_datum_ptr() { return datums_; }
OB_INLINE const ObStorageDatum& get_datum(const int64_t idx) const { OB_ASSERT(idx < datum_cnt_); return datums_[idx]; }
OB_INLINE int64_t get_deep_copy_size() const;
OB_INLINE int deep_copy(ObDatumRowkey &dest, common::ObIAllocator &allocator) const;
OB_INLINE int deep_copy(ObDatumRowkey &dest, char *buf, const int64_t buf_len) const;

View File

@ -19,6 +19,7 @@ namespace oceanbase
{
namespace blocksstable
{
int ObIMicroBlockReader::locate_range(
const ObDatumRange &range,
const bool is_left_border,

View File

@ -22,6 +22,7 @@
#include "storage/access/ob_table_read_info.h"
#include "ob_block_sstable_struct.h"
#include "ob_datum_range.h"
#include "ob_micro_block_hash_index.h"
#include "ob_micro_block_header.h"
namespace oceanbase
@ -50,6 +51,30 @@ struct ObMicroIndexInfo;
} \
} while (0)
template<typename T>
class ObMicroBlockAggInfo {
public:
ObMicroBlockAggInfo(bool is_min, const ObDatumCmpFuncType cmp_fun, T &result_datum) :
is_min_(is_min), cmp_fun_(cmp_fun), result_datum_(result_datum) {}
void update_min_or_max(const T& datum)
{
if (datum.is_null()) {
} else if (result_datum_.is_null()) {
result_datum_ = datum;
} else {
int cmp_ret = cmp_fun_(result_datum_, datum);
if ((is_min_ && cmp_ret > 0) || (!is_min_ && cmp_ret < 0)) {
result_datum_ = datum;
}
}
}
TO_STRING_KV(K_(is_min), K_(cmp_fun), K_(result_datum));
private:
bool is_min_;
const ObDatumCmpFuncType cmp_fun_;
T &result_datum_;
};
struct ObRowIndexIterator
{
public:
@ -208,6 +233,19 @@ public:
const ObTableReadInfo &read_info,
bool &exist,
bool &found) = 0;
protected:
OB_INLINE static int init_hash_index(
const ObMicroBlockData &block_data,
ObMicroBlockHashIndex &hash_index,
const ObMicroBlockHeader *header)
{
int ret = OB_SUCCESS;
hash_index.reset();
if (header->is_contain_hash_index() && OB_FAIL(hash_index.init(block_data))) {
STORAGE_LOG(WARN, "failed to init micro block hash index", K(ret), K(block_data));
}
return ret;
}
};
class ObIMicroBlockReader : public ObIMicroBlockReaderInfo

View File

@ -17,7 +17,7 @@ namespace oceanbase
namespace blocksstable
{
/**
/**
* -------------------------------------------------------------------ObMicroBlockDesc-------------------------------------------------------------------
*/
bool ObMicroBlockDesc::is_valid() const

View File

@ -20,6 +20,7 @@
#include "ob_datum_rowkey.h"
#include "storage/ob_i_store.h"
#include "ob_macro_block_id.h"
#include "ob_micro_block_hash_index.h"
#include "ob_micro_block_header.h"
namespace oceanbase
@ -93,7 +94,8 @@ public:
block_size_upper_bound_(DEFAULT_UPPER_BOUND),
contain_uncommitted_row_(false),
has_out_row_column_(false),
is_last_row_last_flag_(false)
is_last_row_last_flag_(false),
header_(nullptr)
{
}
virtual ~ObIMicroBlockWriter() {}
@ -106,6 +108,16 @@ public:
virtual int64_t get_original_size() const = 0;
virtual void reset() = 0;
virtual void dump_diagnose_info() const {};
virtual int append_hash_index(ObMicroBlockHashIndexBuilder& hash_index_builder)
{
int ret = OB_NOT_SUPPORTED;
STORAGE_LOG(WARN, "Unspported micro block format for hash index", K(ret));
return ret;
}
virtual bool has_enough_space_for_hash_index(const int64_t hash_index_size) const
{
return false;
}
virtual void reuse()
{
row_count_delta_ = 0;
@ -207,6 +219,7 @@ protected:
bool contain_uncommitted_row_;
bool has_out_row_column_;
bool is_last_row_last_flag_;
ObMicroBlockHeader *header_;
};
} // end namespace blocksstable

View File

@ -454,8 +454,11 @@ int ObSSTableIndexBuilder::init(const ObDataStoreDesc &index_desc,
STORAGE_LOG(WARN, "Failed to init index row", K(ret), K(index_desc));
} else {
index_store_desc_.sstable_index_builder_ = this;
index_store_desc_.need_pre_warm_ = true;
callback_ = callback;
optimization_mode_ = mode;
index_store_desc_.need_build_hash_index_for_micro_block_ = false;
container_store_desc_.need_build_hash_index_for_micro_block_ = false;
is_inited_ = true;
}
STORAGE_LOG(DEBUG, "init sstable index builder", K(ret), K(index_desc), K_(index_store_desc));
@ -1089,12 +1092,14 @@ ObBaseIndexBlockBuilder::ObBaseIndexBlockBuilder()
:is_inited_(false),
is_closed_(false),
index_store_desc_(nullptr),
idx_read_info_(),
row_builder_(),
last_rowkey_(),
rowkey_allocator_("BaseBuilder", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()),
allocator_(nullptr),
micro_writer_(nullptr),
macro_writer_(nullptr),
index_block_pre_warmer_(),
row_count_(0),
row_count_delta_(0),
max_merged_trans_version_(0),
@ -1119,6 +1124,7 @@ void ObBaseIndexBlockBuilder::reset()
{
is_closed_ = false;
index_store_desc_ = nullptr;
idx_read_info_.reset();
last_rowkey_.reset();
rowkey_allocator_.reset();
if (OB_NOT_NULL(micro_writer_)) {
@ -1133,6 +1139,7 @@ void ObBaseIndexBlockBuilder::reset()
next_level_builder_ = nullptr;
}
macro_writer_ = nullptr;
index_block_pre_warmer_.reset();
allocator_ = nullptr;
level_ = 0;
reset_accumulative_info();
@ -1153,11 +1160,21 @@ int ObBaseIndexBlockBuilder::init(ObDataStoreDesc &index_store_desc,
allocator_ = &allocator;
macro_writer_ = macro_writer;
level_ = level;
if (OB_FAIL(row_builder_.init(*index_store_desc_))) {
if (!idx_read_info_.is_valid() && OB_FAIL(idx_read_info_.init(allocator,
index_store_desc_->row_column_count_ - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(),
index_store_desc_->schema_rowkey_col_cnt_,
lib::is_oracle_mode(),
index_store_desc_->col_desc_array_,
true))) {
STORAGE_LOG(WARN, "Fail to init index read info", K(ret));
} else if (OB_FAIL(row_builder_.init(*index_store_desc_))) {
STORAGE_LOG(WARN, "fail to init ObBaseIndexBlockBuilder", K(ret));
} else if (OB_FAIL(ObMacroBlockWriter::build_micro_writer(index_store_desc_, allocator, micro_writer_))) {
STORAGE_LOG(WARN, "fail to build micro writer", K(ret));
} else {
if (index_store_desc_->need_pre_warm_) {
index_block_pre_warmer_.init(idx_read_info_);
}
is_inited_ = true;
}
}
@ -1241,6 +1258,7 @@ int ObBaseIndexBlockBuilder::append_row(
int ObBaseIndexBlockBuilder::close(ObIAllocator &allocator, ObIndexTreeInfo &tree_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObBaseIndexBlockBuilder *root_builder = nullptr;
ObIndexTreeRootBlockDesc &desc = tree_info.root_desc_;
if (OB_UNLIKELY(!is_inited_)) {
@ -1271,6 +1289,12 @@ int ObBaseIndexBlockBuilder::close(ObIAllocator &allocator, ObIndexTreeInfo &tre
STORAGE_LOG(WARN, "fail to build root block", K(ret));
} else if (FALSE_IT(micro_block_desc.last_rowkey_ = root_builder->last_rowkey_)) {
} else if (OB_UNLIKELY(micro_block_desc.get_block_size() >= ObMetaDiskAddr::ROOT_BLOCK_SIZE_LIMIT)) {
if (index_block_pre_warmer_.is_valid()
&& OB_TMP_FAIL(index_block_pre_warmer_.reserve_kvpair(micro_block_desc, root_builder->level_+1))) {
if (OB_BUF_NOT_ENOUGH != tmp_ret) {
STORAGE_LOG(WARN, "Fail to reserve kvpair", K(tmp_ret));
}
}
if (OB_FAIL(macro_writer_->append_index_micro_block(micro_block_desc))) {
micro_writer->dump_diagnose_info(); // ignore dump error
STORAGE_LOG(WARN, "fail to append root block", K(ret), K(micro_block_desc));
@ -1284,6 +1308,10 @@ int ObBaseIndexBlockBuilder::close(ObIAllocator &allocator, ObIndexTreeInfo &tre
STORAGE_LOG(WARN, "fail to set block address", K(ret), K(root_row_desc));
}
}
if (OB_FAIL(ret) || OB_TMP_FAIL(tmp_ret) || !index_block_pre_warmer_.is_valid()) {
} else if (OB_TMP_FAIL(index_block_pre_warmer_.update_and_put_kvpair(micro_block_desc))) {
STORAGE_LOG(WARN, "Fail to update and put kvpair", K(tmp_ret));
}
} else {
char *&root_buf = desc.buf_;
const int64_t buf_size = micro_block_desc.buf_size_ + micro_block_desc.header_->header_size_;
@ -1341,19 +1369,34 @@ void ObBaseIndexBlockBuilder::clean_status()
int ObBaseIndexBlockBuilder::append_index_micro_block()
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObMicroBlockDesc micro_block_desc;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "invalid base index builder", K(ret), K(is_inited_));
} else if (OB_FAIL(build_index_micro_block(micro_block_desc))) {
STORAGE_LOG(WARN, "fail to build index micro block", K(ret));
} else if (OB_FAIL(macro_writer_->append_index_micro_block(micro_block_desc))) {
micro_writer_->dump_diagnose_info(); // ignore dump error
STORAGE_LOG(WARN, "fail to append index micro block", K(ret), K(micro_block_desc));
} else if (OB_FAIL(append_next_row(micro_block_desc))) {
STORAGE_LOG(WARN, "fail to append next row", K(ret), K(micro_block_desc));
} else if (FALSE_IT(clean_status())) {
} else {
if (index_block_pre_warmer_.is_valid()
&& OB_TMP_FAIL(index_block_pre_warmer_.reserve_kvpair(micro_block_desc, level_+1))) {
if (OB_BUF_NOT_ENOUGH != tmp_ret) {
STORAGE_LOG(WARN, "Fail to reserve kvpair", K(tmp_ret));
}
}
if (OB_FAIL(macro_writer_->append_index_micro_block(micro_block_desc))) {
micro_writer_->dump_diagnose_info(); // ignore dump error
STORAGE_LOG(WARN, "fail to append index micro block", K(ret), K(micro_block_desc));
} else if (OB_FAIL(append_next_row(micro_block_desc))) {
STORAGE_LOG(WARN, "fail to append next row", K(ret), K(micro_block_desc));
} else if (FALSE_IT(clean_status())) {
}
if (OB_FAIL(ret) || OB_TMP_FAIL(tmp_ret) || !index_block_pre_warmer_.is_valid()) {
} else if (OB_TMP_FAIL(index_block_pre_warmer_.update_and_put_kvpair(micro_block_desc))) {
STORAGE_LOG(WARN, "Fail to build index block cache key and put into cache", K(tmp_ret));
}
index_block_pre_warmer_.reuse();
}
return ret;
}
@ -1465,6 +1508,7 @@ void ObBaseIndexBlockBuilder::row_desc_to_meta(
macro_meta.val_.is_last_row_last_flag_ = macro_row_desc.is_last_row_last_flag_;
}
//===================== ObBaseIndexBlockBuilder(private) ================
void ObBaseIndexBlockBuilder::reset_accumulative_info()
{
@ -1550,7 +1594,6 @@ ObDataIndexBlockBuilder::ObDataIndexBlockBuilder()
sstable_allocator_(nullptr),
leaf_store_desc_(),
micro_helper_(),
idx_read_info_(),
macro_row_desc_(),
root_micro_block_desc_(nullptr),
macro_meta_list_(nullptr),
@ -1573,7 +1616,6 @@ void ObDataIndexBlockBuilder::reset()
sstable_builder_ = nullptr;
leaf_store_desc_.reset();
micro_helper_.reset();
idx_read_info_.reset();
root_micro_block_desc_ = nullptr;
macro_meta_list_ = nullptr;
if (OB_NOT_NULL(meta_block_writer_)) {
@ -1836,19 +1878,32 @@ int ObDataIndexBlockBuilder::append_index_micro_block(ObMacroBlock &macro_block,
const MacroBlockId &block_id)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
ObMicroBlockDesc leaf_block_desc; // n-1 level index block
int64_t data_offset = 0;
int64_t leaf_block_size = 0;
if (OB_FAIL(build_index_micro_block(leaf_block_desc))) {
STORAGE_LOG(WARN, "fail to build n-1 level micro block", K(ret));
} else if (OB_FAIL(micro_helper_.compress_encrypt_micro_block(leaf_block_desc))) {
STORAGE_LOG(WARN, "fail to compress and encrypt micro block", K(ret));
} else if (OB_FAIL(macro_block.write_index_micro_block(leaf_block_desc, true, data_offset))) {
STORAGE_LOG(WARN, "fail to write n-1 level index block", K(ret), K(leaf_block_desc));
} else {
leaf_block_desc.macro_id_ = block_id;
leaf_block_desc.block_offset_ = data_offset;
leaf_block_size = leaf_block_desc.get_block_size();
if (OB_TMP_FAIL(index_block_pre_warmer_.reserve_kvpair(leaf_block_desc, 1))) {
if (OB_BUF_NOT_ENOUGH != tmp_ret) {
STORAGE_LOG(WARN, "Fail to reserve index block value", K(tmp_ret));
}
}
if (OB_FAIL(micro_helper_.compress_encrypt_micro_block(leaf_block_desc))) {
STORAGE_LOG(WARN, "fail to compress and encrypt micro block", K(ret));
} else if (OB_FAIL(macro_block.write_index_micro_block(leaf_block_desc, true, data_offset))) {
STORAGE_LOG(WARN, "fail to write n-1 level index block", K(ret), K(leaf_block_desc));
} else {
leaf_block_desc.macro_id_ = block_id;
leaf_block_desc.block_offset_ = data_offset;
leaf_block_size = leaf_block_desc.get_block_size();
if (OB_TMP_FAIL(tmp_ret)) {
} else if (OB_TMP_FAIL(index_block_pre_warmer_.update_and_put_kvpair(leaf_block_desc))) {
STORAGE_LOG(WARN, "Fail to build index block cache key and put into cache", K(tmp_ret));
}
}
index_block_pre_warmer_.reuse();
}
if (OB_FAIL(ret)) {

View File

@ -20,6 +20,7 @@
#include "storage/blocksstable/ob_micro_block_reader.h"
#include "storage/blocksstable/encoding/ob_micro_block_decoder.h"
#include "storage/meta_mem/ob_meta_obj_struct.h"
#include "share/cache/ob_kvcache_pre_warmer.h"
namespace oceanbase
{
@ -265,10 +266,12 @@ private:
int new_next_builder(ObBaseIndexBlockBuilder *&next_builder);
virtual int append_next_row(const ObMicroBlockDesc &micro_block_desc);
int64_t calc_basic_micro_block_data_offset(const uint64_t column_cnt);
protected:
bool is_inited_;
bool is_closed_;
ObDataStoreDesc *index_store_desc_;
ObTableReadInfo idx_read_info_;
ObIndexBlockRowBuilder row_builder_;
ObDatumRowkey last_rowkey_;
common::ObArenaAllocator rowkey_allocator_;
@ -276,6 +279,7 @@ protected:
ObIMicroBlockWriter *micro_writer_;
ObMacroBlockWriter *macro_writer_;
// accumulative info
ObIndexBlockCachePreWarmer index_block_pre_warmer_;
int64_t row_count_;
int64_t row_count_delta_;
int64_t max_merged_trans_version_;
@ -299,8 +303,7 @@ public:
ObSSTableIndexBuilder &sstable_builder);
int append_row(const ObMicroBlockDesc &micro_block_desc,
const ObMacroBlock &macro_block);
int generate_macro_row(ObMacroBlock &macro_block,
const MacroBlockId &id);
int generate_macro_row(ObMacroBlock &macro_block, const MacroBlockId &id);
int append_macro_block(const ObMacroBlockDesc &macro_desc);
int close(const ObDatumRowkey &last_key,
ObMacroBlocksWriteCtx *data_write_ctx);
@ -324,7 +327,6 @@ private:
ObIAllocator *sstable_allocator_;
ObDataStoreDesc leaf_store_desc_;
ObMicroBlockBufferHelper micro_helper_;
ObTableReadInfo idx_read_info_;
ObIndexBlockRowDesc macro_row_desc_;
ObIndexMicroBlockDesc *root_micro_block_desc_;
ObMacroMetasArray *macro_meta_list_;

View File

@ -15,6 +15,7 @@
#include "lib/utility/ob_tracepoint.h"
#include "ob_block_manager.h"
#include "ob_macro_block.h"
#include "ob_micro_block_hash_index.h"
#include "observer/ob_server_struct.h"
#include "share/ob_encryption_util.h"
#include "share/ob_force_print_log.h"
@ -232,6 +233,19 @@ int ObDataStoreDesc::init(
STORAGE_LOG(INFO, "success to set major working cluster version", K(tmp_ret), K(merge_type), K(cluster_version), K(major_working_cluster_version_));
}
if (OB_SUCC(ret)) {
bool need_build_hash_index = merge_schema.get_table_type() == USER_TABLE
&& !is_major_merge();
if (need_build_hash_index
&& OB_FAIL(ObMicroBlockHashIndexBuilder::need_build_hash_index(merge_schema, need_build_hash_index))) {
STORAGE_LOG(WARN, "Failed to judge whether to build hash index", K(ret));
need_build_hash_index_for_micro_block_ = false;
ret = OB_SUCCESS;
} else {
need_build_hash_index_for_micro_block_ = need_build_hash_index;
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(col_desc_array_.init(row_column_count_))) {
STORAGE_LOG(WARN, "Failed to reserve column desc array", K(ret));
@ -275,6 +289,7 @@ void ObDataStoreDesc::reset()
rowkey_column_count_ = 0;
schema_rowkey_col_cnt_ = 0;
row_store_type_ = ENCODING_ROW_STORE;
need_build_hash_index_for_micro_block_ = false;
encoder_opt_.reset();
schema_version_ = 0;
merge_info_ = NULL;
@ -291,6 +306,7 @@ void ObDataStoreDesc::reset()
major_working_cluster_version_ = 0;
sstable_index_builder_ = nullptr;
is_ddl_ = false;
need_pre_warm_ = false;
col_desc_array_.reset();
datum_utils_.reset();
allocator_.reset();
@ -308,6 +324,7 @@ int ObDataStoreDesc::assign(const ObDataStoreDesc &desc)
row_column_count_ = desc.row_column_count_;
rowkey_column_count_ = desc.rowkey_column_count_;
row_store_type_ = desc.row_store_type_;
need_build_hash_index_for_micro_block_ = desc.need_build_hash_index_for_micro_block_;
schema_version_ = desc.schema_version_;
schema_rowkey_col_cnt_ = desc.schema_rowkey_col_cnt_;
encoder_opt_ = desc.encoder_opt_;
@ -323,6 +340,7 @@ int ObDataStoreDesc::assign(const ObDataStoreDesc &desc)
MEMCPY(encrypt_key_, desc.encrypt_key_, sizeof(encrypt_key_));
major_working_cluster_version_ = desc.major_working_cluster_version_;
is_ddl_ = desc.is_ddl_;
need_pre_warm_ = desc.need_pre_warm_;
col_desc_array_.reset();
datum_utils_.reset();
sstable_index_builder_ = desc.sstable_index_builder_;

View File

@ -56,6 +56,7 @@ struct ObDataStoreDesc
int64_t row_column_count_;
int64_t rowkey_column_count_;
ObRowStoreType row_store_type_;
bool need_build_hash_index_for_micro_block_;
int64_t schema_version_;
int64_t schema_rowkey_col_cnt_;
ObMicroBlockEncoderOpt encoder_opt_;
@ -77,6 +78,7 @@ struct ObDataStoreDesc
// which still use freezeinfo without cluster version
int64_t major_working_cluster_version_;
bool is_ddl_;
bool need_pre_warm_;
common::ObArenaAllocator allocator_;
common::ObFixedArray<share::schema::ObColDesc, common::ObIAllocator> col_desc_array_;
blocksstable::ObStorageDatumUtils datum_utils_;

212
src/storage/blocksstable/ob_macro_block_writer.cpp Normal file → Executable file
View File

@ -355,6 +355,7 @@ ObMacroBlockWriter::ObMacroBlockWriter()
:data_store_desc_(nullptr),
micro_writer_(nullptr),
reader_helper_(),
hash_index_builder_(),
micro_helper_(),
read_info_(),
current_index_(0),
@ -372,7 +373,8 @@ ObMacroBlockWriter::ObMacroBlockWriter()
datum_row_(),
check_datum_row_(),
callback_(nullptr),
builder_(NULL)
builder_(NULL),
data_block_pre_warmer_()
{
//macro_blocks_, macro_handles_
}
@ -391,6 +393,7 @@ void ObMacroBlockWriter::reset()
micro_writer_ = nullptr;
}
reader_helper_.reset();
hash_index_builder_.reset();
micro_helper_.reset();
read_info_.reset();
macro_blocks_[0].reset();
@ -415,6 +418,7 @@ void ObMacroBlockWriter::reset()
micro_block_adaptive_splitter_.reset();
allocator_.reset();
rowkey_allocator_.reset();
data_block_pre_warmer_.reset();
}
@ -435,59 +439,60 @@ int ObMacroBlockWriter::open(
} else {
STORAGE_LOG(DEBUG, "open macro block writer: ", K(data_store_desc), K(start_seq));
ObSSTableIndexBuilder *sstable_index_builder = data_store_desc.sstable_index_builder_;
if (OB_NOT_NULL(sstable_index_builder)) {
callback_ = callback;
data_store_desc_ = &data_store_desc;
current_macro_seq_ = start_seq.get_data_seq();
if (OB_FAIL(init_hash_index_builder())) {
STORAGE_LOG(WARN, "Failed to build hash_index builder", K(ret));
} else if (OB_FAIL(build_micro_writer(data_store_desc_,
allocator_,
micro_writer_,
GCONF.micro_block_merge_verify_level))) {
STORAGE_LOG(WARN, "fail to build micro writer", K(ret));
} else if (OB_FAIL(read_info_.init(
allocator_,
data_store_desc.row_column_count_ - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(),
data_store_desc.schema_rowkey_col_cnt_,
lib::is_oracle_mode(),
data_store_desc.col_desc_array_,
true))) {
STORAGE_LOG(WARN, "failed to init read info", K(data_store_desc), K(ret));
} else if (OB_FAIL(datum_row_.init(allocator_, read_info_.get_request_count()))) {
STORAGE_LOG(WARN, "Failed to init datum row", K(ret), K_(read_info));
} else if (OB_FAIL(micro_helper_.open(data_store_desc, read_info_, allocator_))) {
STORAGE_LOG(WARN, "Failed to open micro helper", K(ret), K_(read_info));
} else if (OB_FAIL(check_datum_row_.init(allocator_, read_info_.get_request_count()))) {
STORAGE_LOG(WARN, "Failed to init datum row", K(ret), K_(read_info));
} else if (OB_FAIL(reader_helper_.init(allocator_))) {
STORAGE_LOG(WARN, "Failed to init reader helper", K(ret));
} else {
//TODO huronghui.hrh@oceanbase.com use 4.1.0.0 for version judgment
const bool is_use_adaptive = !data_store_desc_->is_major_merge()
|| data_store_desc_->major_working_cluster_version_ >= DATA_VERSION_4_1_0_0;
if (OB_FAIL(micro_block_adaptive_splitter_.init(data_store_desc.macro_store_size_, is_use_adaptive))) {
STORAGE_LOG(WARN, "Failed to init micro block adaptive split", K(ret), K(data_store_desc.macro_store_size_));
}
}
if (OB_SUCC(ret) && data_store_desc_->is_major_merge()) {
if (OB_ISNULL(curr_micro_column_checksum_ = static_cast<int64_t *>(
allocator_.alloc(sizeof(int64_t) * data_store_desc_->row_column_count_)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "fail to allocate memory for curr micro block column checksum", K(ret));
} else {
MEMSET(curr_micro_column_checksum_, 0,
sizeof(int64_t) * data_store_desc_->row_column_count_);
}
}
if (OB_FAIL(ret)) {
} else if (OB_NOT_NULL(sstable_index_builder)) {
if (OB_FAIL(sstable_index_builder->new_index_builder(builder_, data_store_desc, allocator_))) {
STORAGE_LOG(WARN, "fail to alloc index builder", K(ret));
} else if (data_store_desc.need_pre_warm_) {
data_block_pre_warmer_.init(read_info_);
}
} else {
builder_ = nullptr;
}
if (OB_SUCC(ret)) {
callback_ = callback;
data_store_desc_ = &data_store_desc;
current_macro_seq_ = start_seq.get_data_seq();
if (OB_FAIL(build_micro_writer(data_store_desc_,
allocator_,
micro_writer_,
GCONF.micro_block_merge_verify_level))) {
STORAGE_LOG(WARN, "fail to build micro writer", K(ret));
} else if (OB_FAIL(read_info_.init(
allocator_,
data_store_desc.row_column_count_ - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(),
data_store_desc.schema_rowkey_col_cnt_,
lib::is_oracle_mode(),
data_store_desc.col_desc_array_,
true))) {
STORAGE_LOG(WARN, "failed to init read info", K(data_store_desc), K(ret));
} else if (OB_FAIL(datum_row_.init(allocator_, read_info_.get_request_count()))) {
STORAGE_LOG(WARN, "Failed to init datum row", K(ret), K_(read_info));
} else if (OB_FAIL(micro_helper_.open(data_store_desc, read_info_, allocator_))) {
STORAGE_LOG(WARN, "Failed to open micro helper", K(ret), K_(read_info));
} else if (OB_FAIL(check_datum_row_.init(allocator_, read_info_.get_request_count()))) {
STORAGE_LOG(WARN, "Failed to init datum row", K(ret), K_(read_info));
} else if (OB_FAIL(reader_helper_.init(allocator_))) {
STORAGE_LOG(WARN, "Failed to init reader helper", K(ret));
} else {
//TODO huronghui.hrh@oceanbase.com use 4.1.0.0 for version judgment
const bool is_use_adaptive = !data_store_desc_->is_major_merge()
|| data_store_desc_->major_working_cluster_version_ >= DATA_VERSION_4_1_0_0;
if (OB_FAIL(micro_block_adaptive_splitter_.init(data_store_desc.macro_store_size_, is_use_adaptive))) {
STORAGE_LOG(WARN, "Failed to init micro block adaptive split", K(ret), K(data_store_desc.macro_store_size_));
}
}
if (OB_SUCC(ret) && data_store_desc_->is_major_merge()) {
if (OB_ISNULL(curr_micro_column_checksum_ = static_cast<int64_t *>(
allocator_.alloc(sizeof(int64_t) * data_store_desc_->row_column_count_)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "fail to allocate memory for curr micro block column checksum", K(ret));
} else {
MEMSET(curr_micro_column_checksum_, 0,
sizeof(int64_t) * data_store_desc_->row_column_count_);
}
}
}
}
return ret;
}
@ -522,17 +527,17 @@ int ObMacroBlockWriter::append_row(const ObDatumRow &row, const int64_t split_si
} else if (OB_FAIL(check_order(row))) {
STORAGE_LOG(WARN, "macro block writer fail to check order.", K(row));
}
if (OB_SUCC(ret) ){
if (OB_SUCC(ret)) {
is_macro_or_micro_block_reused_ = false;
const ObStorageDatumUtils &datum_utils = read_info_.get_datum_utils();
if (OB_FAIL(micro_writer_->append_row(*row_to_append))) {
if (OB_FAIL(append_row_and_hash_index(*row_to_append))) {
if (OB_BUF_NOT_ENOUGH == ret) {
if (0 == micro_writer_->get_row_count()) {
ret = OB_NOT_SUPPORTED;
STORAGE_LOG(ERROR, "The single row is too large, ", K(ret), K(row));
} else if (OB_FAIL(build_micro_block())) {
STORAGE_LOG(WARN, "Fail to build micro block, ", K(ret));
} else if (OB_FAIL(micro_writer_->append_row(*row_to_append))) {
} else if (OB_FAIL(OB_FAIL(append_row_and_hash_index(*row_to_append)))) {
STORAGE_LOG(ERROR, "Fail to append row to micro block, ", K(ret), K(row));
} else if (OB_FAIL(save_last_key(*row_to_append))) {
STORAGE_LOG(WARN, "Fail to save last key, ", K(ret), K(row));
@ -844,6 +849,44 @@ int ObMacroBlockWriter::check_order(const ObDatumRow &row)
return ret;
}
int ObMacroBlockWriter::init_hash_index_builder()
{
int ret = OB_SUCCESS;
if (data_store_desc_->need_build_hash_index_for_micro_block_
&& OB_FAIL(hash_index_builder_.init(data_store_desc_))) {
STORAGE_LOG(WARN, "Failed to build hash_index builder", K(ret));
}
return ret;
}
int ObMacroBlockWriter::append_row_and_hash_index(const ObDatumRow &row)
{
int ret = OB_SUCCESS;
if (OB_FAIL(micro_writer_->append_row(row))) {
if (ret != OB_BUF_NOT_ENOUGH) {
STORAGE_LOG(WARN, "Failed to append row in micro writer", K(ret), K(row));
}
} else if (hash_index_builder_.is_valid()) {
if (OB_UNLIKELY(FLAT_ROW_STORE != data_store_desc_->row_store_type_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected row store type", K(ret), K(data_store_desc_->row_store_type_));
} else {
int64_t hash_index_size = hash_index_builder_.estimate_size(true);
if (OB_UNLIKELY(!micro_writer_->has_enough_space_for_hash_index(hash_index_size))) {
ret = OB_BUF_NOT_ENOUGH;
} else if (OB_FAIL(hash_index_builder_.add(row))) {
if (ret != OB_NOT_SUPPORTED) {
STORAGE_LOG(WARN, "Failed to append hash index", K(ret), K(row));
} else {
ret = OB_SUCCESS;
}
hash_index_builder_.reset();
}
}
}
return ret;
}
int ObMacroBlockWriter::append_index_micro_block(ObMicroBlockDesc &micro_block_desc)
{
// used to append normal index micro block
@ -867,6 +910,7 @@ int ObMacroBlockWriter::append_index_micro_block(ObMicroBlockDesc &micro_block_d
int ObMacroBlockWriter::build_micro_block()
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
int64_t block_size = 0;
ObMicroBlockDesc micro_block_desc;
if (micro_writer_->get_row_count() <= 0) {
@ -874,21 +918,40 @@ int ObMacroBlockWriter::build_micro_block()
STORAGE_LOG(WARN, "micro_block_writer is empty", K(ret));
} else if (OB_FAIL(micro_writer_->build_micro_block_desc(micro_block_desc))) {
STORAGE_LOG(WARN, "failed to build micro block desc", K(ret));
} else if (FALSE_IT(micro_block_desc.last_rowkey_ = last_key_)) {
} else if (FALSE_IT(block_size = micro_block_desc.buf_size_)) {
} else if (OB_FAIL(micro_helper_.compress_encrypt_micro_block(micro_block_desc))) {
micro_writer_->dump_diagnose_info(); // ignore dump error
STORAGE_LOG(WARN, "failed to compress and encrypt micro block", K(ret), K(micro_block_desc));
} else if (OB_FAIL(build_hash_index_block(micro_block_desc))) {
STORAGE_LOG(WARN, "Failed to build hash index block", K(ret));
} else {
if (OB_FAIL(write_micro_block(micro_block_desc))) {
STORAGE_LOG(WARN, "fail to write micro block ", K(ret), K(micro_block_desc));
} else if (OB_FAIL(micro_block_adaptive_splitter_.update_compression_info(micro_block_desc.row_count_,
block_size, micro_block_desc.buf_size_))) {
STORAGE_LOG(WARN, "Fail to update_compression_info", K(ret), K(micro_block_desc));
micro_block_desc.last_rowkey_ = last_key_;
block_size = micro_block_desc.buf_size_;
if (data_block_pre_warmer_.is_valid()
&& OB_TMP_FAIL(data_block_pre_warmer_.reserve_kvpair(micro_block_desc))) {
if (OB_BUF_NOT_ENOUGH != tmp_ret) {
STORAGE_LOG(WARN, "Fail to reserve data block cache value", K(tmp_ret));
}
}
if (OB_FAIL(micro_helper_.compress_encrypt_micro_block(micro_block_desc))) {
micro_writer_->dump_diagnose_info(); // ignore dump error
STORAGE_LOG(WARN, "failed to compress and encrypt micro block", K(ret), K(micro_block_desc));
} else {
if (OB_FAIL(write_micro_block(micro_block_desc))) {
STORAGE_LOG(WARN, "fail to write micro block ", K(ret), K(micro_block_desc));
} else if (OB_FAIL(micro_block_adaptive_splitter_.update_compression_info(micro_block_desc.row_count_,
block_size, micro_block_desc.buf_size_))) {
STORAGE_LOG(WARN, "Fail to update_compression_info", K(ret), K(micro_block_desc));
}
if (OB_FAIL(ret) || !data_block_pre_warmer_.is_valid() || OB_TMP_FAIL(tmp_ret)) {
} else if (OB_TMP_FAIL(data_block_pre_warmer_.update_and_put_kvpair(micro_block_desc))) {
STORAGE_LOG(WARN, "Fail to build data cache key and put into cache", K(tmp_ret));
}
}
data_block_pre_warmer_.reuse();
}
if (OB_SUCC(ret)) {
micro_writer_->reuse();
if (data_store_desc_->need_build_hash_index_for_micro_block_) {
hash_index_builder_.reuse();
}
if (data_store_desc_->need_prebuild_bloomfilter_ && micro_rowkey_hashs_.count() > 0) {
micro_rowkey_hashs_.reuse();
}
@ -898,7 +961,8 @@ int ObMacroBlockWriter::build_micro_block()
data_store_desc_->merge_info_->new_micro_count_in_new_macro_++;
}
}
STORAGE_LOG(DEBUG, "build micro block desc", K(data_store_desc_->tablet_id_), K(micro_block_desc), "lbt", lbt(), K(ret));
STORAGE_LOG(DEBUG, "build micro block desc", K(data_store_desc_->tablet_id_), K(micro_block_desc), "lbt", lbt(),
K(ret), K(tmp_ret));
return ret;
}
@ -926,6 +990,29 @@ int ObMacroBlockWriter::build_micro_block_desc(
return ret;
}
int ObMacroBlockWriter::build_hash_index_block(ObMicroBlockDesc &micro_block_desc)
{
int ret = OB_SUCCESS;
if (hash_index_builder_.is_valid()) {
if (OB_UNLIKELY(FLAT_ROW_STORE != data_store_desc_->row_store_type_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected row store type", K(ret), K(data_store_desc_->row_store_type_));
} else if (OB_FAIL(micro_writer_->append_hash_index(hash_index_builder_))) {
if (ret != OB_NOT_SUPPORTED) {
LOG_WARN("Failed to append hash index to micro block writer", K(ret));
} else {
ret = OB_SUCCESS;
}
hash_index_builder_.reset();
} else {
const int64_t hash_index_size = hash_index_builder_.estimate_size();
micro_block_desc.buf_size_ += hash_index_size;
micro_block_desc.data_size_ += hash_index_size;
}
}
return ret;
}
int ObMacroBlockWriter::build_micro_block_desc_with_reuse(
const ObMicroBlock &micro_block,
ObMicroBlockDesc &micro_block_desc)
@ -1045,6 +1132,7 @@ int ObMacroBlockWriter::write_micro_block(ObMicroBlockDesc &micro_block_desc)
}
}
if (OB_FAIL(ret)) {
} else if (FALSE_IT(micro_block_desc.macro_id_ = macro_handles_[current_index_].get_macro_id())) {
} else if (OB_FAIL(macro_blocks_[current_index_].write_micro_block(micro_block_desc, data_offset))) {
STORAGE_LOG(WARN, "Fail to write micro block, ", K(ret), K(micro_block_desc));
} else if (OB_UNLIKELY(micro_block_desc.block_offset_ != data_offset)) {

View File

@ -29,6 +29,7 @@
#include "share/schema/ob_table_schema.h"
#include "ob_bloom_filter_cache.h"
#include "ob_micro_block_reader_helper.h"
#include "share/cache/ob_kvcache_pre_warmer.h"
namespace oceanbase
{
@ -159,10 +160,13 @@ protected:
private:
int append_row(const ObDatumRow &row, const int64_t split_size);
int check_order(const ObDatumRow &row);
int init_hash_index_builder();
int append_row_and_hash_index(const ObDatumRow &row);
int build_micro_block_desc(
const ObMicroBlock &micro_block,
ObMicroBlockDesc &micro_block_desc,
ObMicroBlockHeader &header_for_rewrite);
int build_hash_index_block(ObMicroBlockDesc &micro_block_desc);
int build_micro_block_desc_with_rewrite(
const ObMicroBlock &micro_block,
ObMicroBlockDesc &micro_block_desc,
@ -198,6 +202,7 @@ protected:
private:
ObIMicroBlockWriter *micro_writer_;
ObMicroBlockReaderHelper reader_helper_;
ObMicroBlockHashIndexBuilder hash_index_builder_;
ObMicroBlockBufferHelper micro_helper_;
ObTableReadInfo read_info_;
ObMacroBlock macro_blocks_[2];
@ -221,6 +226,7 @@ private:
ObIMacroBlockFlushCallback *callback_;
ObDataIndexBlockBuilder *builder_;
ObMicroBlockAdaptiveSplitter micro_block_adaptive_splitter_;
ObDataBlockCachePreWarmer data_block_pre_warmer_;
};
}//end namespace blocksstable

Some files were not shown because too many files have changed in this diff Show More