322 lines
12 KiB
C++
322 lines
12 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#define private public
|
|
#include "storage/blocksstable/ob_column_map.h"
|
|
#include "lib/random/ob_random.h"
|
|
#include "storage/blocksstable/ob_block_sstable_struct.h"
|
|
#include "share/config/ob_server_config.h"
|
|
namespace oceanbase {
|
|
using namespace blocksstable;
|
|
using namespace common;
|
|
namespace unittest {
|
|
class TestColumnMap : public ::testing::Test {
|
|
public:
|
|
virtual void SetUp()
|
|
{}
|
|
virtual void TearDown()
|
|
{}
|
|
static void SetUpTestCase()
|
|
{}
|
|
static void TearDownTestCase()
|
|
{}
|
|
|
|
void test_init(const int result, const int64_t schema_version, const int64_t schema_rowkey_count,
|
|
const int64_t store_count, const ObIArray<share::schema::ObColDesc>& out_cols,
|
|
const share::schema::ColumnMap* cols_id_map = nullptr, const ObIArray<int32_t>* projector = nullptr,
|
|
const bool is_multi_version = false);
|
|
|
|
public:
|
|
ObArenaAllocator allocator_;
|
|
};
|
|
|
|
void TestColumnMap::test_init(const int result, const int64_t schema_version, const int64_t schema_rowkey_count,
|
|
const int64_t store_count, const ObIArray<share::schema::ObColDesc>& out_cols,
|
|
const share::schema::ColumnMap* cols_id_map, const ObIArray<int32_t>* projector, const bool is_multi_version)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObColumnMap map;
|
|
ret = map.init(
|
|
allocator_, schema_version, schema_rowkey_count, store_count, out_cols, cols_id_map, projector, is_multi_version);
|
|
ASSERT_EQ(result, ret);
|
|
if (OB_SUCC(ret)) {
|
|
ASSERT_EQ(out_cols.count(), map.get_request_count());
|
|
ASSERT_EQ(store_count, map.get_store_count());
|
|
ASSERT_EQ(schema_rowkey_count, map.get_rowkey_store_count());
|
|
ASSERT_TRUE(map.is_valid());
|
|
}
|
|
}
|
|
|
|
TEST_F(TestColumnMap, init_invalid)
|
|
{
|
|
ObArray<share::schema::ObColDesc> out_cols;
|
|
test_init(OB_INVALID_ARGUMENT, -1, 2, 10, out_cols);
|
|
test_init(OB_INVALID_ARGUMENT, 1, 0, 10, out_cols);
|
|
test_init(OB_INVALID_ARGUMENT, 1, 2, -1, out_cols);
|
|
test_init(OB_INVALID_ARGUMENT, 1, 2, 10, out_cols);
|
|
share::schema::ObColDesc col_desc;
|
|
col_desc.col_id_ = 1 + OB_APP_MIN_COLUMN_ID;
|
|
col_desc.col_type_.set_type(static_cast<ObObjType>(ObInt32Type));
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col_desc));
|
|
test_init(OB_SUCCESS, 1, 2, 10, out_cols);
|
|
col_desc.col_id_ = 2 + OB_APP_MIN_COLUMN_ID;
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col_desc));
|
|
test_init(OB_SUCCESS, 1, 2, 10, out_cols);
|
|
test_init(OB_SUCCESS, 1, 2, 10, out_cols, nullptr, nullptr, true);
|
|
test_init(OB_SUCCESS, 1, 2, 10, out_cols, nullptr, nullptr, false);
|
|
test_init(OB_INVALID_ARGUMENT, 1, 2, 1, out_cols);
|
|
test_init(OB_INVALID_ARGUMENT, 1, 2, OB_ROW_MAX_COLUMNS_COUNT + 1, out_cols);
|
|
out_cols.reuse();
|
|
for (int64_t i = 0; i < OB_ROW_MAX_COLUMNS_COUNT + 1; ++i) {
|
|
col_desc.col_id_ = i + OB_APP_MIN_COLUMN_ID;
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col_desc));
|
|
}
|
|
test_init(OB_INVALID_ARGUMENT, 1, 2, 10, out_cols);
|
|
|
|
out_cols.reuse();
|
|
col_desc.col_id_ = 7;
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col_desc));
|
|
col_desc.col_id_ = 8;
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col_desc));
|
|
ObArray<int32_t> projector;
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(0));
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(1));
|
|
test_init(OB_SUCCESS, 1, 2, 10, out_cols, nullptr, &projector);
|
|
projector.reuse();
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(-1));
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(-2));
|
|
test_init(OB_SUCCESS, 1, 2, 10, out_cols, nullptr, &projector);
|
|
projector.reuse();
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(0));
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(10));
|
|
test_init(OB_INVALID_ARGUMENT, 1, 2, 10, out_cols, nullptr, &projector);
|
|
test_init(OB_SUCCESS, 1, 2, 0, out_cols, nullptr, &projector);
|
|
projector.reuse();
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(0));
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(OB_ROW_MAX_COLUMNS_COUNT));
|
|
test_init(OB_INVALID_ARGUMENT, 1, 2, 0, out_cols, nullptr, &projector);
|
|
}
|
|
|
|
TEST_F(TestColumnMap, init_cols)
|
|
{
|
|
ObColumnMap map;
|
|
ObArray<share::schema::ObColDesc> out_cols;
|
|
const int64_t schema_version = 1;
|
|
const int64_t rowkey_count = 2;
|
|
const int64_t column_count = ObHexStringType;
|
|
for (int64_t i = 0; i < column_count; ++i) {
|
|
share::schema::ObColDesc col;
|
|
col.col_id_ = static_cast<uint64_t>(i + OB_APP_MIN_COLUMN_ID);
|
|
col.col_type_.set_type(static_cast<ObObjType>(i));
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col));
|
|
}
|
|
ASSERT_EQ(OB_SUCCESS, map.init(allocator_, schema_version, rowkey_count, column_count, out_cols));
|
|
ASSERT_EQ(out_cols.count(), map.get_request_count());
|
|
ASSERT_EQ(rowkey_count, map.get_rowkey_store_count());
|
|
ASSERT_EQ(out_cols.count(), map.get_seq_read_column_count());
|
|
const ObColumnIndexItem* column_indexs = map.get_column_indexs();
|
|
for (int64_t i = 0; i < map.get_request_count(); ++i) {
|
|
ASSERT_EQ(column_indexs[i].column_id_, out_cols[i].col_id_);
|
|
ASSERT_EQ(column_indexs[i].store_index_, i);
|
|
ASSERT_EQ(column_indexs[i].request_column_type_, out_cols[i].col_type_);
|
|
ASSERT_EQ(column_indexs[i].is_column_type_matched_, true);
|
|
}
|
|
}
|
|
|
|
TEST_F(TestColumnMap, init_projector)
|
|
{
|
|
ObColumnMap map;
|
|
ObArray<share::schema::ObColDesc> out_cols;
|
|
const int64_t schema_version = 1;
|
|
const int64_t rowkey_count = 2;
|
|
const int64_t column_count = ObHexStringType;
|
|
for (int64_t i = 0; i < column_count; ++i) {
|
|
share::schema::ObColDesc col;
|
|
col.col_id_ = static_cast<uint64_t>(i + OB_APP_MIN_COLUMN_ID);
|
|
col.col_type_.set_type(static_cast<ObObjType>(i));
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col));
|
|
}
|
|
|
|
ObArray<int32_t> projector;
|
|
for (int64_t i = 0; i < column_count; ++i) {
|
|
const int64_t store_index = ObRandom::rand(0, column_count - 1);
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(static_cast<int32_t>(store_index)));
|
|
}
|
|
ASSERT_EQ(
|
|
OB_SUCCESS, map.init(allocator_, schema_version, rowkey_count, column_count, out_cols, nullptr, &projector));
|
|
ASSERT_EQ(out_cols.count(), map.get_request_count());
|
|
ASSERT_EQ(rowkey_count, map.get_rowkey_store_count());
|
|
const ObColumnIndexItem* column_indexs = map.get_column_indexs();
|
|
for (int64_t i = 0; i < map.get_request_count(); ++i) {
|
|
ASSERT_EQ(column_indexs[i].column_id_, out_cols[i].col_id_);
|
|
ASSERT_EQ(column_indexs[i].store_index_, projector[i]);
|
|
ASSERT_EQ(column_indexs[i].request_column_type_, out_cols[i].col_type_);
|
|
ASSERT_EQ(column_indexs[i].is_column_type_matched_, true);
|
|
}
|
|
}
|
|
|
|
TEST_F(TestColumnMap, init_multi_version)
|
|
{
|
|
ObColumnMap map;
|
|
|
|
// test sequence columns with multi version
|
|
ObArray<share::schema::ObColDesc> out_cols;
|
|
const int64_t schema_version = 1;
|
|
const int64_t rowkey_count = 2;
|
|
const int64_t column_count = ObHexStringType;
|
|
for (int64_t i = 0; i < column_count; ++i) {
|
|
share::schema::ObColDesc col;
|
|
col.col_id_ = static_cast<uint64_t>(i + OB_APP_MIN_COLUMN_ID);
|
|
col.col_type_.set_type(static_cast<ObObjType>(i));
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col));
|
|
}
|
|
int extra_col_cnt = storage::ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt();
|
|
const ObColumnIndexItem* column_indexs = nullptr;
|
|
|
|
// test projector with multi version
|
|
map.reset();
|
|
ObArray<int32_t> projector;
|
|
for (int64_t i = 0; i < column_count; ++i) {
|
|
const int64_t store_index = ObRandom::rand(0, column_count - 1);
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(static_cast<int32_t>(store_index)));
|
|
}
|
|
ASSERT_EQ(OB_SUCCESS,
|
|
map.init(allocator_, schema_version, rowkey_count, column_count, out_cols, nullptr, &projector, extra_col_cnt));
|
|
ASSERT_EQ(out_cols.count(), map.get_request_count());
|
|
column_indexs = map.get_column_indexs();
|
|
for (int64_t i = 0; i < map.get_request_count(); ++i) {
|
|
ASSERT_EQ(column_indexs[i].column_id_, out_cols[i].col_id_);
|
|
if (projector[i] < rowkey_count) {
|
|
ASSERT_EQ(column_indexs[i].store_index_, projector[i]);
|
|
} else {
|
|
ASSERT_EQ(column_indexs[i].store_index_, projector[i] + extra_col_cnt);
|
|
}
|
|
ASSERT_EQ(column_indexs[i].request_column_type_, out_cols[i].col_type_);
|
|
ASSERT_EQ(column_indexs[i].is_column_type_matched_, true);
|
|
}
|
|
}
|
|
|
|
TEST_F(TestColumnMap, test_column_hash)
|
|
{
|
|
int64_t column_cnt = 5;
|
|
uint16_t column_ids[5] = {16, 17, 18, 19, 30};
|
|
ObColumnHashSet column_hash;
|
|
ObArenaAllocator allocator;
|
|
ASSERT_EQ(OB_SUCCESS, column_hash.init(column_cnt, column_ids, allocator));
|
|
int64_t idx = -1;
|
|
for (int64_t i = 0; i < column_cnt; ++i) {
|
|
column_hash.get_index(column_ids[i], idx);
|
|
ASSERT_EQ(i, idx);
|
|
}
|
|
column_hash.get_index(20, idx);
|
|
ASSERT_EQ(-1, idx);
|
|
|
|
column_cnt = 4;
|
|
column_ids[0] = 16;
|
|
column_ids[1] = 32;
|
|
column_ids[2] = 48;
|
|
column_ids[3] = 24;
|
|
ASSERT_EQ(OB_SUCCESS, column_hash.init(column_cnt, column_ids, allocator));
|
|
idx = -1;
|
|
for (int64_t i = 0; i < column_cnt; ++i) {
|
|
column_hash.get_index(column_ids[i], idx);
|
|
ASSERT_EQ(i, idx);
|
|
}
|
|
column_hash.get_index(20, idx);
|
|
ASSERT_EQ(-1, idx);
|
|
ASSERT_EQ(13, column_hash.shift_);
|
|
for (int64_t i = 0; i <= 8; ++i) {
|
|
STORAGE_LOG(INFO, "column hash bucket", K(i), K(column_hash.bucket_[i]));
|
|
}
|
|
for (int64_t i = 0; i < column_cnt; ++i) {
|
|
STORAGE_LOG(INFO, "column hash chain", K(i), K(column_hash.chain_[i]));
|
|
}
|
|
}
|
|
|
|
TEST_F(TestColumnMap, rebuild_perf)
|
|
{
|
|
ObColumnMap map;
|
|
ObArray<share::schema::ObColDesc> out_cols;
|
|
const int64_t schema_version = 1;
|
|
const int64_t rowkey_count = 1;
|
|
const int64_t column_count = ObHexStringType;
|
|
for (int64_t i = 0; i < column_count; i += 2) {
|
|
share::schema::ObColDesc col;
|
|
col.col_id_ = static_cast<uint64_t>(i + OB_APP_MIN_COLUMN_ID);
|
|
col.col_type_.set_type(static_cast<ObObjType>(i));
|
|
ASSERT_EQ(OB_SUCCESS, out_cols.push_back(col));
|
|
}
|
|
|
|
ObArray<int32_t> projector;
|
|
for (int64_t i = 0; i < column_count; i += 2) {
|
|
ASSERT_EQ(OB_SUCCESS, projector.push_back(i));
|
|
}
|
|
ASSERT_EQ(
|
|
OB_SUCCESS, map.init(allocator_, schema_version, rowkey_count, column_count, out_cols, nullptr, &projector));
|
|
ObMacroBlockMetaV2 macro_meta;
|
|
ObMacroBlockSchemaInfo macro_schema;
|
|
ObFullMacroBlockMeta full_meta;
|
|
full_meta.meta_ = ¯o_meta;
|
|
full_meta.schema_ = ¯o_schema;
|
|
macro_meta.schema_version_ = 1;
|
|
macro_meta.column_number_ = column_count;
|
|
macro_schema.schema_version_ = 1;
|
|
macro_schema.column_number_ = column_count;
|
|
uint16_t column_ids[column_count];
|
|
ObObjMeta column_types[column_count];
|
|
for (int64_t i = 0; i < column_count; ++i) {
|
|
column_ids[i] = static_cast<uint16_t>(i + OB_APP_MIN_COLUMN_ID);
|
|
column_types[i].set_type(static_cast<ObObjType>(i));
|
|
}
|
|
macro_schema.column_id_array_ = column_ids;
|
|
macro_schema.column_type_array_ = column_types;
|
|
|
|
const int64_t start_time = ObTimeUtility::current_time();
|
|
for (int64_t i = 0; i < 10000000; ++i) {
|
|
map.rebuild(full_meta, true);
|
|
}
|
|
const int64_t elapsed_time = ObTimeUtility::current_time() - start_time;
|
|
STORAGE_LOG(INFO, "rebuild perf cost", K(elapsed_time));
|
|
ASSERT_EQ(out_cols.count(), map.get_request_count());
|
|
ASSERT_EQ(rowkey_count, map.get_rowkey_store_count());
|
|
const ObColumnIndexItem* column_indexs = map.get_column_indexs();
|
|
for (int64_t i = 0; i < map.get_request_count(); ++i) {
|
|
ASSERT_EQ(column_indexs[i].column_id_, out_cols[i].col_id_);
|
|
ASSERT_EQ(column_indexs[i].store_index_, projector[i]);
|
|
ASSERT_EQ(column_indexs[i].request_column_type_, out_cols[i].col_type_);
|
|
ASSERT_EQ(column_indexs[i].is_column_type_matched_, true);
|
|
}
|
|
int filled_cnt = 0;
|
|
int64_t cnt = 1 << (16 - map.column_hash_.shift_);
|
|
for (int64_t i = 0; i < cnt; ++i) {
|
|
if (map.column_hash_.bucket_[i] != -1) {
|
|
filled_cnt++;
|
|
}
|
|
STORAGE_LOG(INFO, "bucket content", K(i), K(map.column_hash_.bucket_[i]));
|
|
}
|
|
STORAGE_LOG(INFO, "bucket stat", K(filled_cnt), K(column_count), K(cnt));
|
|
}
|
|
|
|
} // end namespace unittest
|
|
} // end namespace oceanbase
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
GCONF._enable_sparse_row = false;
|
|
system("rm -rf test_column_map.log");
|
|
OB_LOGGER.set_file_name("test_column_map.log");
|
|
oceanbase::common::ObLogger::get_logger().set_log_level("INFO");
|
|
testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|