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();
 | 
						|
}
 |