【问题标题】:rocksdb merge operarator performance is very slow for large number of keysrocksdb 合并运算符对于大量键的性能非常慢
【发布时间】:2023-02-02 23:54:56
【问题描述】:

我试图弄清楚为什么将合并运算符用于 rocksdb 的大量键非常慢。

我的程序使用一个简单的关联合并运算符 (based on upstream StringAppendOperator),它使用给定键的定界符连接值。合并所有键和程序完成运行需要很长时间。

PS:我从源代码构建了 rocksdb - latest master。我不确定我是否遗漏了一些非常明显的东西。

这是一个具有大约 500 万个键的最小可重现示例 - 可以通过更改 for 循环的限制来调整键的数量。先感谢您!

#include <filesystem>
#include <iostream>
#include <utility>

#include <rocksdb/db.h>
#include "rocksdb/merge_operator.h"

// Based on: https://github.com/facebook/rocksdb/blob/main/utilities/merge_operators/string_append/stringappend.h#L13
class StringAppendOperator : public rocksdb::AssociativeMergeOperator
{
public:
    // Constructor: specify delimiter
    explicit StringAppendOperator(std::string delim) : delim_(std::move(delim)) {};

    bool Merge(const rocksdb::Slice &key, const rocksdb::Slice *existing_value,
                       const rocksdb::Slice &value, std::string *new_value,
                       rocksdb::Logger *logger) const override;

    static const char *kClassName() { return "StringAppendOperator"; }
    static const char *kNickName() { return "stringappend"; }
    [[nodiscard]] const char *Name() const override { return kClassName(); }
    [[nodiscard]] const char *NickName() const override { return kNickName(); }

private:
    std::string delim_;// The delimiter is inserted between elements
};

// Implementation for the merge operation (concatenates two strings)
bool StringAppendOperator::Merge(const rocksdb::Slice & /*key*/,
                                 const rocksdb::Slice *existing_value,
                                 const rocksdb::Slice &value, std::string *new_value,
                                 rocksdb::Logger * /*logger*/) const
{
    // Clear the *new_value for writing.
    assert(new_value);
    new_value->clear();

    if (!existing_value)
    {
        // No existing_value. Set *new_value = value
        new_value->assign(value.data(), value.size());
    }
    else
    {
        // Generic append (existing_value != null).
        // Reserve *new_value to correct size, and apply concatenation.
        new_value->reserve(existing_value->size() + delim_.size() + value.size());
        new_value->assign(existing_value->data(), existing_value->size());
        new_value->append(delim_);
        new_value->append(value.data(), value.size());
        std::cout << "Merging " << value.data() << "\n";
    }
    return true;
}


int main()
{
    rocksdb::Options options;
    options.create_if_missing = true;
    options.merge_operator.reset(new StringAppendOperator(","));

    # tried a variety of settings
    options.max_background_compactions = 16;
    options.max_background_flushes = 16;
    options.max_background_jobs = 16;
    options.max_subcompactions = 16;

    rocksdb::DB *db{};
    auto s = rocksdb::DB::Open(options, "/tmp/test", &db);
    assert(s.ok());

    rocksdb::WriteBatch wb;
    for (uint64_t i = 0; i < 2500000; i++)
    {
        wb.Merge("a:b", std::to_string(i));
        wb.Merge("c:d", std::to_string(i));
    }
    db->Write(rocksdb::WriteOptions(), &wb);
    db->Flush(rocksdb::FlushOptions());

    rocksdb::ReadOptions read_options;
    rocksdb::Iterator *it = db->NewIterator(read_options);

    for (it->SeekToFirst(); it->Valid(); it->Next())
    {
        std::cout << it->key().ToString() << " --> " << it->value().ToString() << "\n";
    }
    delete it;
    delete db;
    std::filesystem::remove_all("/tmp/test");
    return 0;
}

【问题讨论】:

  • 这里有问题吗?

标签: c++ rocksdb


【解决方案1】:

在 Discord 上的 Speedb Hive 中分享您的问题。 回复来自我们的联合创始人兼首席科学家 Hilik。

'合并运算符对于获得快速写入响应时间非常有用,唉,读取需要读取原始文件并按顺序应用合并。此操作可能非常昂贵,尤其是在每次合并时都需要复制和附加字符串。解决这个问题的最简单方法是使用 read modify write eventually 。在应用程序级别执行此操作是可能的,但可能会出现问题(如果两个线程可以同时执行此操作)。我们正在考虑在压实过程中解决这个问题的方法,并愿意与您合作进行公关......'

希望这可以帮助。加入discord服务器参与本次讨论以及其他许多有趣和相关的话题。 Here 是关于您的主题的讨论链接

【讨论】:

    猜你喜欢
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    相关资源
    最近更新 更多