Быстро вставьте МНОГИЕ пары ключ-значение в Беркли БД с хеш-доступом - PullRequest
2 голосов
/ 27 мая 2010

Я пытаюсь создать хеш с помощью berkeley db, который должен содержать много кортежей (около 18 ГБ пар ключей-значений), но во всех моих тестах производительность операций вставки со временем резко падает. Я написал этот скрипт для проверки производительности:

#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);
    }

}

Возможно, вы можете сказать мне, почему через некоторое время операция "put" занимает все больше времени и, возможно, как это исправить.

Спасибо за вашу помощь, Andreas

Ответы [ 4 ]

3 голосов
/ 02 июня 2010

Возможно, вы захотите взглянуть на информацию, предоставляемую утилитой db_stat, и на доступные для настройки функции HASH. См. Раздел Справочное руководство по BDB по настройке базы данных HASH .

.

Я ожидаю, что вы получите 10 с тысяч вставок в секунду на обычном оборудовании. Что вы испытываете и какова ваша цель?

С уважением,

Dave

3 голосов
/ 03 июня 2010

Я бы порекомендовал попробовать API массовой вставки, об этом вы можете прочитать в документации здесь: http://www.oracle.com/technology/documentation/berkeley-db/db/api_reference/CXX/dbput.html#put_DB_MULTIPLE_KEY

Кроме того, я бы предположил, что ваш вызов memp_trickle ответственен за большую часть замедления. По мере того, как кэш становится все более грязным, поиск нужных страниц становится все дороже. Фактически, поскольку вы только пишете, большой кэш только причиняет боль (как только вы записали данные, вы больше не используете их, поэтому не хотите, чтобы они оставались в кеше). Я бы порекомендовал тестирование разных (меньших) размеров кеша.

Наконец, если ваша единственная забота - производительность вставки, поможет использование большего размера страницы. Вы сможете разместить больше данных на каждой странице, что приведет к уменьшению количества записей на диск.

-Бен

1 голос
/ 27 октября 2010

memp_trickle почти наверняка замедляет работу. Часто полезно использовать струйку, но она должна быть эффективной в своем потоке. BDB (за исключением случаев, когда вы входите в API-интерфейсы репликации более высокого уровня) не создает для вас потоков - ничего не происходит за кулисами (по потокам). струйка будет эффективна, когда грязные страницы будут вытеснены из кэша (посмотрите на вывод статистики, чтобы увидеть, происходит ли это).

Вы можете также рассмотреть возможность использования BTREE вместо HASH. Да, я знаю, что ты специально сказал хэш, но почему? Если вы хотите максимизировать производительность, зачем добавлять это ограничение? Возможно, вы сможете воспользоваться ссылочным местоположением, чтобы уменьшить объем кэш-памяти - часто вы полагаете, что гораздо больше локали, или, возможно, вы можете создать их - если вы генерируете ключи со случайными цифрами, например, перед датой и время. Это обычно вводит локальность в воспринимаемую «случайную» систему. Если вы используете btree, вам нужно будет обратить внимание на порядок следования байтов для ваших ключей для вашей системы (посмотрите Endianness в Википедии), если вы используете систему Little 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/

0 голосов
/ 27 мая 2010

У вашей производительности может быть несколько причин, которые на самом деле не связаны с вашим кодом. Я могу ошибаться, но я думаю, что это все о внутренней структуре базы данных (и используется структура данных ).

Подумайте о ситуации, когда в базе данных используется какой-то подход, отличный от хеш-таблицы , например, RB Tree . Для вставки в это дерево потребуется O(logN) в смысле Big-O, и каждый вставленный элемент увеличивает время, необходимое для вставки next .

К сожалению, то же самое может произойти с простой хэш-таблицей , так что начальное время операции вставки O(1) ухудшается до чего-то худшего. Это может иметь несколько причин, но это все о коллизиях хеша , которые могут произойти из-за неправильной хэш-функции, неправильных данных (то есть плохо для используемой в настоящее время хэш-функции) или даже из-за фаза луны.

На вашем месте я бы попытался покопаться во внутренней структуре вашей БД. Кроме того, я думаю, что тестирование ваших ключей с чем-то другим, кроме вашей базы данных (например, boost::unordered_map), также может принести пользу вашему тестированию и профилированию.

Edit: Также упомянуть, вы пытались изменить это cache_size материал в вашем образце? Или, может быть, есть другие параметры, связанные с производительностью, которые можно изменить?

...