Skip to content

Commit

Permalink
Add new command: show index chunk info (#1275)
Browse files Browse the repository at this point in the history
### What problem does this PR solve?

Show index segment chunk detailed information.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
  • Loading branch information
JinHai-CN authored Jun 2, 2024
1 parent a755221 commit b35bfdc
Show file tree
Hide file tree
Showing 25 changed files with 2,902 additions and 2,430 deletions.
70 changes: 70 additions & 0 deletions docs/references/http_api_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,76 @@ curl --request GET \
}
```

## Show index segment

Show detailed information of a specified index segment.

#### Request

```
curl --request GET \
--url localhost:23820/databases/{database_name}/tables/{table_name}/indexes/{index_name}/segment/{segment_id} \
--header 'accept: application/json'
```

#### Response

- 200 Success.

```
{
"error_code":0,
"chunk_count":"1",
"index_segment_size":"290.41MB",
"segment_id":"0",
"storage_path":"/var/infinity/data/XScyuGgMEf_db_default_db/X7Ilrg2jG1_table_sift_benchmark/gWao7rl6u4_index_hnsw_index"
}
```

- 500 Error.

```
{
"error_code": 3018,
"error_message": "Index {index_name} doesn't exist in {table_name}."
}
```

## Show index chunk

Show detailed information of a index chunk of specified index chunk.

#### Request

```
curl --request GET \
--url localhost:23820/databases/{database_name}/tables/{table_name}/indexes/{index_name}/segment/{segment_id}/chunk/{chunk_id} \
--header 'accept: application/json'
```

#### Response

- 200 Success.

```
{
"error_code":0,
"deprecate_timestamp":"18446744073709551615",
"file_name":"",
"row_count":"1000000",
"start_row":"0"
}
```

- 500 Error.

```
{
"error_code": 3018,
"error_message": "Index {index_name} doesn't exist in {table_name}."
}
```

## List indexes

Lists all indexes of a specified table.
Expand Down
1 change: 1 addition & 0 deletions python/infinity/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class ErrorCode(IntEnum):
INVALID_ANALYZER_NAME = 3079,
INVALID_ANALYZER_FILE = 3080,
INVALID_EXPLAIN_TYPE = 3081,
CHUNK_NOT_EXIST = 3082,

TXN_ROLLBACK = 4001,
TXN_CONFLICT = 4002,
Expand Down
9 changes: 7 additions & 2 deletions src/common/status.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,11 @@ Status Status::DuplicateColumnName(const String &column_name) {

Status Status::InvalidExpression(const String &expr_str) { return Status(ErrorCode::kInvalidExpression, MakeUnique<String>(expr_str)); }

Status Status::SegmentNotExist(const SegmentID &segment_id) {
Status Status::SegmentNotExist(SegmentID segment_id) {
return Status(ErrorCode::kSegmentNotExist, MakeUnique<String>(fmt::format("Segment: {} doesn't exist", segment_id)));
}
Status Status::BlockNotExist(const BlockID &block_id) {

Status Status::BlockNotExist(BlockID block_id) {
return Status(ErrorCode::kBlockNotExist, MakeUnique<String>(fmt::format("Block: {} doesn't exist", block_id)));
}

Expand Down Expand Up @@ -394,6 +395,10 @@ Status Status::InvalidAnalyzerFile(const String& detailed_info) {
return Status(ErrorCode::kInvalidAnalyzerName, MakeUnique<String>(fmt::format("Invalid analyzer file path: {}", detailed_info)));
}

Status Status::ChunkNotExist(ChunkID chunk_id) {
return Status(ErrorCode::kChunkNotExist, MakeUnique<String>(fmt::format("Index chunk: {} doesn't exist", chunk_id)));
}

// 4. TXN fail
Status Status::TxnRollback(u64 txn_id) {
return Status(ErrorCode::kTxnRollback, MakeUnique<String>(fmt::format("Transaction: {} is rollback", txn_id)));
Expand Down
6 changes: 4 additions & 2 deletions src/common/status.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export enum class ErrorCode : long {
kInvalidAnalyzerName = 3079,
kInvalidAnalyzerFile = 3080,
kInvalidExplainType = 3081,
kChunkNotExist = 3082,

// 4. Txn fail
kTxnRollback = 4001,
Expand Down Expand Up @@ -258,14 +259,15 @@ public:
static Status InvalidJsonFormat(const String& invalid_json);
static Status DuplicateColumnName(const String& column_name);
static Status InvalidExpression(const String& expr_str);
static Status SegmentNotExist(const SegmentID &segment_id);
static Status BlockNotExist(const BlockID &block_id);
static Status SegmentNotExist(SegmentID segment_id);
static Status BlockNotExist(BlockID block_id);
static Status AggregateFunctionWithEmptyArgs();
static Status InvalidCommand(const String& detailed_error);
static Status AnalyzerNotFound(const String& name);
static Status NotSupportedAnalyzer(const String& name);
static Status InvalidAnalyzerName(const String& name);
static Status InvalidAnalyzerFile(const String& detailed_info);
static Status ChunkNotExist(ChunkID chunk_id);

// 4. TXN fail
static Status TxnRollback(u64 txn_id);
Expand Down
18 changes: 18 additions & 0 deletions src/executor/explain_physical_plan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,24 @@ void ExplainPhysicalPlan::Explain(const PhysicalShow *show_node, SharedPtr<Vecto
result->emplace_back(MakeShared<String>(output_columns_str));
break;
}
case ShowType::kShowIndexChunk: {
String show_str;
if (intent_size != 0) {
show_str = String(intent_size - 2, ' ');
show_str += "-> SHOW INDEX CHUNK";
} else {
show_str = "SHOW INDEX CHUNK";
}
show_str += "(";
show_str += std::to_string(show_node->node_id());
show_str += ")";
result->emplace_back(MakeShared<String>(show_str));

String output_columns_str = String(intent_size, ' ');
output_columns_str += " - output columns: [name, value]";
result->emplace_back(MakeShared<String>(output_columns_str));
break;
}
case ShowType::kShowTables: {
String show_str;
if (intent_size != 0) {
Expand Down
163 changes: 162 additions & 1 deletion src/executor/operator/physical_show.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import catalog;
import txn_manager;
import wal_manager;
import logger;
import chunk_index_entry;

namespace infinity {

Expand Down Expand Up @@ -111,6 +112,15 @@ void PhysicalShow::Init() {
output_types_->emplace_back(varchar_type);
break;
}
case ShowType::kShowIndexChunk: {
output_names_->reserve(2);
output_types_->reserve(2);
output_names_->emplace_back("name");
output_types_->emplace_back(varchar_type);
output_names_->emplace_back("value");
output_types_->emplace_back(varchar_type);
break;
}
case ShowType::kShowDatabases: {
output_names_->reserve(1);
output_types_->reserve(1);
Expand Down Expand Up @@ -393,6 +403,10 @@ bool PhysicalShow::Execute(QueryContext *query_context, OperatorState *operator_
ExecuteShowIndexSegment(query_context, show_operator_state);
break;
}
case ShowType::kShowIndexChunk: {
ExecuteShowIndexChunk(query_context, show_operator_state);
break;
}
case ShowType::kShowDatabases: {
ExecuteShowDatabases(query_context, show_operator_state);
break;
Expand Down Expand Up @@ -897,7 +911,7 @@ void PhysicalShow::ExecuteShowIndexSegment(QueryContext *query_context, ShowOper
{
SizeT column_id = 0;
{
Value value = Value::MakeVarchar("segment id");
Value value = Value::MakeVarchar("segment_id");
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}
Expand Down Expand Up @@ -1001,6 +1015,153 @@ void PhysicalShow::ExecuteShowIndexSegment(QueryContext *query_context, ShowOper
show_operator_state->output_.emplace_back(std::move(output_block_ptr));
}

void PhysicalShow::ExecuteShowIndexChunk(QueryContext *query_context, ShowOperatorState *show_operator_state) {
// Define output table detailed info
auto varchar_type = MakeShared<DataType>(LogicalType::kVarchar);

// Get tables from catalog
Txn *txn = query_context->GetTxn();

auto [table_entry, status1] = txn->GetTableByName(db_name_, object_name_);
if (!status1.ok()) {
LOG_ERROR(status1.message());
RecoverableError(status1);
return;
}

auto [table_index_entry, status2] = txn->GetIndexByName(db_name_, object_name_, index_name_.value());
if (!status2.ok()) {
LOG_ERROR(status2.message());
RecoverableError(status2);
return;
}

Map<SegmentID, SharedPtr<SegmentIndexEntry>> segment_map = table_index_entry->GetIndexBySegmentSnapshot(table_entry, txn);
auto iter = segment_map.find(segment_id_.value());
if(iter == segment_map.end()) {
show_operator_state->status_ = Status::SegmentNotExist(segment_id_.value());
LOG_ERROR(show_operator_state->status_.message());
RecoverableError(show_operator_state->status_);
}

SegmentIndexEntry* segment_index_entry = iter->second.get();
IndexBase* index_base = table_index_entry->table_index_def().get();
String index_type_name = IndexInfo::IndexTypeToString(index_base->index_type_);

Vector<SharedPtr<ChunkIndexEntry>> chunk_indexes;
switch(index_base->index_type_) {
case IndexType::kIVFFlat: {
Status status3 = Status::InvalidIndexName(index_type_name);
show_operator_state->status_ = status3;
LOG_ERROR(fmt::format("{} isn't implemented.", index_type_name));
RecoverableError(status3);
break;
}
case IndexType::kHnsw: {
auto [chunk_index_entries, _] = segment_index_entry->GetHnswIndexSnapshot();
chunk_indexes = chunk_index_entries;
break;
}
case IndexType::kFullText: {
auto [chunk_index_entries, _] = segment_index_entry->GetFullTextIndexSnapshot();
chunk_indexes = chunk_index_entries;
break;
}
case IndexType::kSecondary: {
auto [chunk_index_entries, _] = segment_index_entry->GetSecondaryIndexSnapshot();
chunk_indexes = chunk_index_entries;
break;
}
case IndexType::kInvalid: {
Status status3 = Status::InvalidIndexName(index_type_name);
LOG_ERROR(fmt::format("{} is invalid.", index_type_name));
RecoverableError(status3);
break;
}
}

ChunkID chunk_id = chunk_id_.value();
if(chunk_id >= chunk_indexes.size()) {
show_operator_state->status_ = Status::ChunkNotExist(chunk_id);
LOG_ERROR(show_operator_state->status_.message());
RecoverableError(show_operator_state->status_);
}

ChunkIndexEntry* chunk_index_entry = chunk_indexes[chunk_id].get();

// Prepare the output data block
UniquePtr<DataBlock> output_block_ptr = DataBlock::MakeUniquePtr();
Vector<SharedPtr<DataType>> column_types{varchar_type, varchar_type};

output_block_ptr->Init(column_types);

{
SizeT column_id = 0;
{
Value value = Value::MakeVarchar("file_name");
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}

++column_id;
{
Value value = Value::MakeVarchar(chunk_index_entry->base_name_);
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}
}

{
SizeT column_id = 0;
{
Value value = Value::MakeVarchar("start_row");
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}

++column_id;
{
Value value = Value::MakeVarchar(chunk_index_entry->base_rowid_.ToString());
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}
}

{
SizeT column_id = 0;
{
Value value = Value::MakeVarchar("row_count");
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}

++column_id;
{
Value value = Value::MakeVarchar(std::to_string(chunk_index_entry->row_count_));
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}
}

{
SizeT column_id = 0;
{
Value value = Value::MakeVarchar("deprecate_timestamp");
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}

++column_id;
{
Value value = Value::MakeVarchar(std::to_string(chunk_index_entry->deprecate_ts_));
ValueExpression value_expr(value);
value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]);
}
}

output_block_ptr->Finalize();
show_operator_state->output_.emplace_back(std::move(output_block_ptr));
}

/**
* @brief Execute show table
Expand Down
Loading

0 comments on commit b35bfdc

Please sign in to comment.