Add automatic index creation functionality

This commit is contained in:
gvolfing 2024-03-20 16:13:42 +01:00
parent be32e8893d
commit 1788e60691
6 changed files with 67 additions and 13 deletions

View File

@ -1905,8 +1905,11 @@ void DiskStorage::DiskAccessor::FinalizeTransaction() {
}
}
utils::BasicResult<StorageIndexDefinitionError, void> DiskStorage::DiskAccessor::CreateIndex(LabelId label) {
MG_ASSERT(unique_guard_.owns_lock(), "Create index requires unique access to the storage!");
utils::BasicResult<StorageIndexDefinitionError, void> DiskStorage::DiskAccessor::CreateIndex(
LabelId label, bool unique_access_needed) {
if (unique_access_needed) {
MG_ASSERT(unique_guard_.owns_lock(), "Create index requires unique access to the storage!");
}
auto *on_disk = static_cast<DiskStorage *>(storage_);
auto *disk_label_index = static_cast<DiskLabelIndex *>(on_disk->indices_.label_index_.get());
if (!disk_label_index->CreateIndex(label, on_disk->SerializeVerticesForLabelIndex(label))) {
@ -1934,7 +1937,8 @@ utils::BasicResult<StorageIndexDefinitionError, void> DiskStorage::DiskAccessor:
return {};
}
utils::BasicResult<StorageIndexDefinitionError, void> DiskStorage::DiskAccessor::CreateIndex(EdgeTypeId /*edge_type*/) {
utils::BasicResult<StorageIndexDefinitionError, void> DiskStorage::DiskAccessor::CreateIndex(
EdgeTypeId /*edge_type*/, bool /*unique_access_needed*/) {
throw utils::NotYetImplemented(
"Edge-type index related operations are not yet supported using on-disk storage mode.");
}

View File

@ -160,11 +160,13 @@ class DiskStorage final : public Storage {
void FinalizeTransaction() override;
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label) override;
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label,
bool unique_access_needed = true) override;
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label, PropertyId property) override;
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(EdgeTypeId edge_type) override;
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(EdgeTypeId edge_type,
bool unique_access_needed = true) override;
utils::BasicResult<StorageIndexDefinitionError, void> DropIndex(LabelId label) override;

View File

@ -315,6 +315,13 @@ Result<EdgeAccessor> InMemoryStorage::InMemoryAccessor::CreateEdge(VertexAccesso
guard_from.lock();
}
// TODO short-circuit
if (storage_->config_.salient.items.enable_edge_type_index_auto_creation) {
if (!storage_->indices_.edge_type_index_->IndexExists(edge_type)) {
storage_->edge_types_to_auto_index_->emplace(edge_type);
}
}
if (!PrepareForWrite(&transaction_, from_vertex)) return Error::SERIALIZATION_ERROR;
if (from_vertex->deleted) return Error::DELETED_OBJECT;
@ -805,6 +812,25 @@ utils::BasicResult<StorageManipulationError, void> InMemoryStorage::InMemoryAcce
{
std::unique_lock<utils::SpinLock> engine_guard(storage_->engine_lock_);
if (storage_->config_.salient.items.enable_label_index_auto_creation) {
storage_->labels_to_auto_index_.WithLock([&](auto &label_indices) {
for (const auto label : label_indices) {
CreateIndex(label, false);
}
label_indices.clear();
});
}
if (storage_->config_.salient.items.enable_edge_type_index_auto_creation) {
storage_->edge_types_to_auto_index_.WithLock([&](auto &edge_type_indices) {
for (const auto edge_type : edge_type_indices) {
CreateIndex(edge_type, false);
}
edge_type_indices.clear();
});
}
auto *mem_unique_constraints =
static_cast<InMemoryUniqueConstraints *>(storage_->constraints_.unique_constraints_.get());
commit_timestamp_.emplace(mem_storage->CommitTimestamp(reparg.desired_commit_timestamp));
@ -1253,8 +1279,11 @@ void InMemoryStorage::InMemoryAccessor::FinalizeTransaction() {
}
}
utils::BasicResult<StorageIndexDefinitionError, void> InMemoryStorage::InMemoryAccessor::CreateIndex(LabelId label) {
MG_ASSERT(unique_guard_.owns_lock(), "Creating label index requires a unique access to the storage!");
utils::BasicResult<StorageIndexDefinitionError, void> InMemoryStorage::InMemoryAccessor::CreateIndex(
LabelId label, bool unique_access_needed) {
if (unique_access_needed) {
MG_ASSERT(unique_guard_.owns_lock(), "Creating label index requires a unique access to the storage!");
}
auto *in_memory = static_cast<InMemoryStorage *>(storage_);
auto *mem_label_index = static_cast<InMemoryLabelIndex *>(in_memory->indices_.label_index_.get());
if (!mem_label_index->CreateIndex(label, in_memory->vertices_.access(), std::nullopt)) {
@ -1282,8 +1311,10 @@ utils::BasicResult<StorageIndexDefinitionError, void> InMemoryStorage::InMemoryA
}
utils::BasicResult<StorageIndexDefinitionError, void> InMemoryStorage::InMemoryAccessor::CreateIndex(
EdgeTypeId edge_type) {
MG_ASSERT(unique_guard_.owns_lock(), "Create index requires a unique access to the storage!");
EdgeTypeId edge_type, bool unique_access_needed) {
if (unique_access_needed) {
MG_ASSERT(unique_guard_.owns_lock(), "Create index requires a unique access to the storage!");
}
auto *in_memory = static_cast<InMemoryStorage *>(storage_);
auto *mem_edge_type_index = static_cast<InMemoryEdgeTypeIndex *>(in_memory->indices_.edge_type_index_.get());
if (!mem_edge_type_index->CreateIndex(edge_type, in_memory->vertices_.access())) {

View File

@ -241,7 +241,8 @@ class InMemoryStorage final : public Storage {
/// * `IndexDefinitionError`: the index already exists.
/// * `ReplicationError`: there is at least one SYNC replica that has not confirmed receiving the transaction.
/// @throw std::bad_alloc
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label) override;
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label,
bool unique_access_needed = true) override;
/// Create an index.
/// Returns void if the index has been created.
@ -257,7 +258,8 @@ class InMemoryStorage final : public Storage {
/// * `ReplicationError`: there is at least one SYNC replica that has not confirmed receiving the transaction.
/// * `IndexDefinitionError`: the index already exists.
/// @throw std::bad_alloc
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(EdgeTypeId edge_type) override;
utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(EdgeTypeId edge_type,
bool unique_access_needed = true) override;
/// Drop an existing index.
/// Returns void if the index has been dropped.

View File

@ -272,11 +272,13 @@ class Storage {
std::vector<EdgeTypeId> ListAllPossiblyPresentEdgeTypes() const;
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label) = 0;
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label,
bool unique_access_needed = true) = 0;
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label, PropertyId property) = 0;
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(EdgeTypeId edge_type) = 0;
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(EdgeTypeId edge_type,
bool unique_access_needed = true) = 0;
virtual utils::BasicResult<StorageIndexDefinitionError, void> DropIndex(LabelId label) = 0;
@ -435,6 +437,12 @@ class Storage {
utils::SynchronizedMetaDataStore<LabelId> stored_node_labels_;
utils::SynchronizedMetaDataStore<EdgeTypeId> stored_edge_types_;
// Sets that hold onto labels and edge-types that have to be created.
// Used only if the label/edge-type autocreation flags are enabled,
// does not affect index creation otherwise.
utils::Synchronized<std::set<LabelId>, utils::SpinLock> labels_to_auto_index_;
utils::Synchronized<std::set<EdgeTypeId>, utils::SpinLock> edge_types_to_auto_index_;
std::atomic<uint64_t> vertex_id_{0};
std::atomic<uint64_t> edge_id_{0};
};

View File

@ -118,6 +118,13 @@ Result<bool> VertexAccessor::AddLabel(LabelId label) {
storage_->stored_node_labels_.try_insert(label);
}
// TODO short-circuit
if (storage_->config_.salient.items.enable_label_index_auto_creation) {
if (!storage_->indices_.label_index_->IndexExists(label)) {
storage_->labels_to_auto_index_->emplace(label);
}
}
/// TODO: some by pointers, some by reference => not good, make it better
storage_->constraints_.unique_constraints_->UpdateOnAddLabel(label, *vertex_, transaction_->start_timestamp);
if (transaction_->constraint_verification_info) transaction_->constraint_verification_info->AddedLabel(vertex_);