代码之家  ›  专栏  ›  技术社区  ›  Kungi

使用哈希访问将许多键值对快速插入berkeley db

  •  2
  • Kungi  · 技术社区  · 16 年前

    我试图用berkeleydb构建一个hash,它应该包含许多元组(大约18GB的键值对),但是在我所有的测试中,insert操作的性能会随着时间的推移而急剧下降。我编写这个脚本是为了测试性能:

    #include<iostream>
    #include<db_cxx.h>
    #include<ctime>
    
    #define MILLION 1000000
    
    int main () {
        long long a = 0;
        long long b = 0;
    
        int passes = 0;
        int i = 0;
        u_int32_t flags = DB_CREATE;
    
        Db* dbp = new Db(NULL,0);
        dbp->set_cachesize( 0, 1024 * 1024 * 1024, 1 );
    
        int ret = dbp->open(
                NULL,
                "test.db",
                NULL,
                DB_HASH,
                flags,
                0);
        time_t time1 = time(NULL);
    
        while ( passes < 100 ) {
            while( i < MILLION ) {
    
                Dbt key( &a, sizeof(long long) );
                Dbt data( &b, sizeof(long long) );
    
                dbp->put( NULL, &key, &data, 0);
                a++; b++; i++;  
            }
    
            DbEnv* dbep = dbp->get_env();
            int tmp;
            dbep->memp_trickle( 50, &tmp );
    
            i=0;
            passes++;
            std::cout << "Inserted one million --> pass: " << passes << " took: " << time(NULL) - time1 << "sec" << std::endl;
            time1 = time(NULL);
        }
    
    }
    

    谢谢你的帮助, 安德烈亚斯

    4 回复  |  直到 16 年前
        1
  •  3
  •   dsegleau    16 年前

    您可能需要查看由db\u stat实用程序提供的信息以及可用的特定于哈希的调优函数。请看 BDB Reference Guide section on configuring a HASH database

    我希望你能在商品硬件上每秒得到10万个插件。你经历了什么?你的绩效目标是什么?

    当做,

    戴夫

        2
  •  3
  •   Ben Schmeckpeper    16 年前

    http://www.oracle.com/technology/documentation/berkeley-db/db/api_reference/CXX/dbput.html#put_DB_MULTIPLE_KEY

    另外,我猜你打电话给mempèu涓流是造成经济放缓的主要原因。随着缓存变得越来越脏,查找要滴流的页面变得更加昂贵。事实上,由于您只是在写,拥有一个大的缓存只会带来伤害(一旦您写了数据,就不会再使用它,所以您不希望它在缓存中徘徊。)我建议测试不同(较小)的缓存大小。

    最后,如果您唯一关心的是插入性能,那么使用较大的页面大小将有所帮助。您将能够在每一页上容纳更多的数据,从而减少磁盘写入。

    -本

        3
  •  1
  •   Don Anderson    15 年前

    您还可以考虑使用BTREE而不是HASH。是的,我知道你特别说哈什,但为什么?如果您希望最大化性能,为什么要添加此限制?您可以利用引用的局部性来减少缓存占用空间—通常您相信的局部性要多得多,或者您可以创建一些—如果您生成的键是随机数字,例如,在日期和时间之前加上前缀。这通常会将局部性引入到一个可感知的“随机”系统中。如果您使用btree,您需要注意系统密钥的字节顺序(在Wikipedia中查找Endianness),如果您使用的是小Endian系统,则需要交换字节。使用具有正确顺序和引入的局部性的BTREE意味着您的键/值对将以“键生成时间”的顺序存储,因此,如果您看到最近的键上的大多数操作,您将倾向于反复访问相同的页(请在统计信息中查看缓存命中率)。所以你需要更少的缓存。另一种方法是,在相同的缓存量下,您的解决方案将按更大的倍数进行扩展。

    我希望你的实际应用程序真的没有按顺序插入整数键(如果有,你会很幸运)。因此,您应该编写一个与您的访问模式非常接近的基准测试,至少在以下方面:键的大小、数据的大小、访问模式、数据库中的项目数、读/写混合。一旦你有了这些,看看统计数据——密切关注任何暗示IO或争用的东西。

    顺便说一句,我最近在 http://libdb.wordpress.com 讨论BDB性能调整(以及与BDB相关的其他事项)。你可能会在那里得到一些好主意。延迟和吞吐量可能会有很大的差异,这取决于您所做的调优类型。具体见 http://libdb.wordpress.com/2011/01/31/revving-up-a-benchmark-from-626-to-74000-operations-per-second/

        4
  •  0
  •   M. Williams    16 年前

    性能下降可能有几个原因,这些原因实际上与代码无关。我可能弄错了,但我认为这完全是关于内部数据库结构(和 ).

    哈希表 ,例如 RB树 . 插进那棵树里要花很多时间 O(logN) 在Big-O意义上,每个插入的元素都会增加 插入。

    哈希表 O(1) 杂凑碰撞

    如果我是你,我会努力挖掘你的db内部结构。此外,我认为测试你的钥匙与其他东西,而不是你的数据库(例如 boost::unordered_map )也有利于您的测试和分析。

    编辑:还要提的是,你有没有试着改变这一点 cache_size