// you’re reading...

Programming

Ужасающие тормоза вторичных бд в Berkeley DB

Сейчас я работаю над прототипом для сериализации данных через БД. Для тестового варианта (видимо это лучшее, что имеется на сегоднешний день) мы взяли Berkeley DB. Нужна была “встраиваемая” БД, работающая в терминах b-tree. SQL синтаксис значительно увеличивает тормоза (примерно в 2 раза) хотя и предостовляет значительно большие возможности. Интересная проблема с которой я столкнулся — это жуткие тормоза, вплоть до полного зависания программы при обработке большого количества входных данных. Как оказалось, это эффект от использования вторичных БД (secondary db) как метода индексирования записей.

Допустим, что у вас есть база сотрудников типа: “пол;имя;должность”, где ключ=“пол;имя”. Весьма вероятно, что вам захочется делать запросы к этой базе типа: “выдать мне всех сотрудников мужского пола”. Berkeley DB не поддерживает запросы в стиле SQL, так что для такого рода запросов понадобится создавать “добавочную” БД, у которой ключом будет “пол” и которая будет поддерживать дубликаты (иначе у нас при таком запросе будет выведена 1 запись). Для этого и существуют secondary db. Они ссылаются на записи первичной БД, используя свой собственный ключ. Ключ secondary db задается преобразованием данных из первичной БД, т.е. функцией, которая на вход принимает данные первичной БД, а возвращает ключ secondary db.

В описанной схеме проблема возникнет в случае, когда у вас огромное количество сотрудников. Так как ключ secondary db это всего лишь “пол”, а значит он может принимать 2 значения, то каждому значению ключа будет соответствовать множество сотрудников (соответственно мужского или женского пола). В случае, если количество ваших сотрудников стремится к 2 — 3 миллионам, то готовтесь, что обращение к первичной БД начнет на столько “тормозить”, что почти остановит работу системы.

Пример

{
  // open databases
  db_open_default (&db_people, "people.db", 0);
  db_open_default (&db_sex2people, "sex2people.db", DB_DUP);
 
  // associate secondary db with primary db
  // getSex() - function that extracts "sex" field from primary db 'data' field
  db_people->associate (db_people, NULL, db_sex2people, getSex, 0);
 
  for (i = 0; i < 20000000; i++) {
      // prepare data for key,data
      ...
        // write data into db_people
        db_people->put (db_people, NULL, &key, &data, DB_NOOVERWRITE);
  }
}

Через некоторое время операция db_people->put() заставит программу уйти в стопор.


Discussion

Ads

Похожие статьи