From 37b054cd058e6dd9703c4e4ae499f42661dddf75 Mon Sep 17 00:00:00 2001
From: kevinyao0901 <kevinyao0901@163.com>
Date: Wed, 4 Dec 2024 15:25:04 +0800
Subject: [PATCH] upload benchmark

---
 db/db_impl.cc                |   3 +-
 test/Benchmark_test.cc       | 180 +++++++++++++++++++++++++++++++++++++++++++
 test/Secondary_index_test.cc |   2 +-
 3 files changed, 183 insertions(+), 2 deletions(-)
 create mode 100644 test/Benchmark_test.cc

diff --git a/db/db_impl.cc b/db/db_impl.cc
index 151961b..0c01733 100644
--- a/db/db_impl.cc
+++ b/db/db_impl.cc
@@ -1617,9 +1617,10 @@ std::vector<std::string> DBImpl::QueryByIndex(const std::string& fieldName) {
     leveldb::Iterator* it = indexDb_->NewIterator(read_options);
 
     for (it->Seek(fieldName); it->Valid(); it->Next()) {
+        std::string key = it->key().ToString();
         std::string value = it->value().ToString();
         // 仅将非空值添加到结果中
-        if (!value.empty()) {
+        if (key == fieldName && !value.empty()) {
             results.push_back(value);
         }
     }
diff --git a/test/Benchmark_test.cc b/test/Benchmark_test.cc
new file mode 100644
index 0000000..5a587ed
--- /dev/null
+++ b/test/Benchmark_test.cc
@@ -0,0 +1,180 @@
+#include <iostream>
+#include <cassert>
+#include <vector>
+#include <chrono>
+#include <leveldb/db.h>
+
+using namespace std::chrono;
+
+// 定义字段
+struct Field {
+    std::string first;
+    std::string second;
+};
+
+// 解析数据值
+std::vector<std::pair<std::string, std::string>> ParseValue(const std::string& value) {
+    std::vector<std::pair<std::string, std::string>> fields;
+    size_t start = 0;
+    size_t end = value.find("|");
+    
+    while (end != std::string::npos) {
+        std::string field = value.substr(start, end - start);
+        size_t separator = field.find(":");
+        
+        if (separator != std::string::npos) {
+            fields.push_back({field.substr(0, separator), field.substr(separator + 1)});
+        }
+        
+        start = end + 1;
+        end = value.find("|", start);
+    }
+    
+    return fields;
+}
+
+// 查询函数:根据字段查找所有包含该字段的 Key
+std::vector<std::string> FindKeysByField(leveldb::DB* db, const Field& field) {
+    std::vector<std::string> keys;
+    leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
+
+    for (it->SeekToFirst(); it->Valid(); it->Next()) {
+        std::string key = it->key().ToString();
+        std::string value = it->value().ToString();
+
+        std::vector<std::pair<std::string, std::string>> fields = ParseValue(value);
+
+        // 查找是否有匹配的字段
+        for (const auto& f : fields) {
+            if (f.first == field.first && f.second == field.second) {
+                keys.push_back(key);
+                break;
+            }
+        }
+    }
+
+    delete it;
+    return keys;
+}
+
+// 生成数据并插入数据库
+void GenerateAndInsertData(leveldb::DB* db, int num_entries) {
+    leveldb::WriteOptions write_options;
+    leveldb::Status status;
+
+    for (int i = 1; i <= num_entries; ++i) {
+        std::string key = "k_" + std::to_string(i);
+        std::string name = "Customer#" + std::to_string(i);
+        std::string address = "Address_" + std::to_string(i);
+        std::string phone = "25-989-741-" + std::to_string(1000 + i);
+
+        std::string value = "name:" + name + "|address:" + address + "|phone:" + phone;
+
+        status = db->Put(write_options, key, value);
+        assert(status.ok() && "Failed to insert data");
+    }
+}
+
+// 基准测试:二级索引性能提升
+void BenchmarkFieldQueryWithIndex(leveldb::DB* db) {
+    // 测试前,查询无索引的字段性能
+    auto start = high_resolution_clock::now();
+    Field field = {"name", "Customer#10000"};
+    std::vector<std::string> keys_without_index = FindKeysByField(db, field);
+    auto end = high_resolution_clock::now();
+    auto duration = duration_cast<microseconds>(end - start);
+    std::cout << "Time without index: " << duration.count() << " microseconds" << std::endl;
+
+    // 创建二级索引
+    // 在此添加创建索引的代码(可以使用 DBImpl::CreateIndexOnField 函数)
+    start = high_resolution_clock::now();
+    leveldb::Status status = db->CreateIndexOnField("name");
+    end = high_resolution_clock::now();
+    duration = duration_cast<microseconds>(end - start);
+    std::cout << "Time to create index: " << duration.count() << std::endl;
+
+    // 测试后,查询有索引的字段性能
+    start = high_resolution_clock::now();
+    std::vector<std::string> keys_with_index = db->QueryByIndex("name:Customer#10000");  // 使用二级索引查询
+    end = high_resolution_clock::now();
+    duration = duration_cast<microseconds>(end - start);
+    std::cout << "Time with index: " << duration.count() << " microseconds" << std::endl;
+
+    // 输出查询结果
+    std::cout << "Found " << keys_with_index.size() << " keys with index." << std::endl;
+    assert(!keys_with_index.empty() && "Query by index returned no results");
+
+    std::cout << "Query by index results for name=Customer#10000: ";
+    for (const auto& result : keys_with_index) {
+        std::cout << result << ", ";
+    }
+}
+
+// 基准测试:记录插入时的性能影响
+void BenchmarkWritePerformance(leveldb::DB* db, int num_entries) {
+    leveldb::WriteOptions write_options;
+    auto start = high_resolution_clock::now();
+    
+    GenerateAndInsertData(db, num_entries);  // 执行批量插入
+    
+    auto end = high_resolution_clock::now();
+    auto duration = duration_cast<microseconds>(end - start);
+    std::cout << "Insertion time for " << num_entries << " entries: " << duration.count() << " microseconds" << std::endl;
+}
+
+// 基准测试:记录删除二级索引的开销
+void BenchmarkDeleteIndex(leveldb::DB* db, const std::string& field_name) {
+    auto start = high_resolution_clock::now();
+    
+    // 删除二级索引
+    leveldb::Status status = db->DeleteIndex(field_name);
+    assert(status.ok() && "Failed to delete index");
+
+    auto end = high_resolution_clock::now();
+    auto duration = duration_cast<microseconds>(end - start);
+    std::cout << "Time to delete index on field '" << field_name << "': " << duration.count() << " microseconds" << std::endl;
+}
+
+// 获取数据库大小(用来估算二级索引的空间占用)
+void GetDatabaseSize(leveldb::DB* db) {
+    std::string property;
+    
+    // 使用 bool 返回值检查是否成功获取属性
+    bool success = db->GetProperty("leveldb.stats", &property);
+    if (!success) {
+        std::cerr << "Failed to get db stats" << std::endl;
+        return;
+    }
+
+    std::cout << "Database stats: " << std::endl;
+    std::cout << property << std::endl;
+}
+
+int main() {
+    leveldb::Options options;
+    options.create_if_missing = true;
+
+    // 打开数据库
+    leveldb::DB* db = nullptr;
+    leveldb::Status status = leveldb::DB::Open(options, "./testdb", &db);
+    assert(status.ok() && "Failed to open database");
+
+    // 测试写入性能
+    BenchmarkWritePerformance(db, 100001);  // 插入 100001 条数据
+
+    // 测试二级索引对查询性能的提升
+    BenchmarkFieldQueryWithIndex(db);
+
+    // 获取数据库大小
+    GetDatabaseSize(db);
+
+    // 测试删除二级索引的开销
+    BenchmarkDeleteIndex(db, "name");
+
+    // 关闭数据库
+    delete db;
+
+    std::cout << "Benchmark tests completed." << std::endl;
+
+    return 0;
+}
diff --git a/test/Secondary_index_test.cc b/test/Secondary_index_test.cc
index 213affc..ef3a7e0 100644
--- a/test/Secondary_index_test.cc
+++ b/test/Secondary_index_test.cc
@@ -91,4 +91,4 @@ int main() {
     std::cout << "All tests passed." << std::endl;
 
     return 0;
-}
+}
\ No newline at end of file