Berkeleydb - B-Tree против хеш-таблицы - PullRequest
7 голосов
/ 09 ноября 2010

Я пытаюсь понять, что должно определять выбор метода доступа при использовании BerkeleyDB: B-Tree против HashTable. Hashtable обеспечивает поиск O (1), но вставки стоят дорого (используя линейное / расширяемое хеширование, мы получаем амортизированную O (1) для вставки) Но B-Trees обеспечивают поиск в журнале N (основание B) и время вставки. B-дерево также может поддерживать запросы диапазона и разрешать доступ в отсортированном порядке.

  1. Помимо этих соображений, на что еще следует учесть?
  2. Если мне не нужно поддерживать запросы диапазона, могу ли я просто использовать метод доступа Hashtable?

Ответы [ 4 ]

6 голосов
/ 23 августа 2012

Когда ваши наборы данных становятся очень большими, B-деревья все еще лучше, потому что большинство внутренних метаданных могут все еще помещаться в кэш. Хэши по своей природе (равномерное случайное распределение данных) по своей природе недопустимы в кеше. То есть, как только общий размер набора данных превышает объем рабочей памяти, производительность хэша падает с обрыва, в то время как производительность B-дерева изящно снижается (на самом деле логарифмически).

2 голосов
/ 16 ноября 2015

Для многих приложений доступ к базе данных осуществляется случайным образом, в интерактивном режиме или с помощью «транзакций».Это может произойти, если у вас есть данные, поступающие с веб-сервера.Однако вам часто приходится заполнять большую базу данных одновременно, как «пакетную» операцию.Это может произойти, если вы выполняете проект анализа данных или переносите старую базу данных в новый формат.

При одновременном заполнении базы данных предпочтительным является B-дерево или другой отсортированный индекс, поскольку онпозволяет выполнять пакетные вставки гораздо эффективнее.Это достигается путем сортировки ключей перед помещением их в базу данных.Заполнение базы данных BerkeleyDB 10 миллионами записей может занять час, когда записи не отсортированы, потому что каждый доступ является промахом кэша.Но когда записи отсортированы, та же процедура может занять всего десять минут.Близость последовательных клавиш означает, что вы будете использовать различные кэши почти для всех вставок.Сортировка может быть выполнена очень быстро, поэтому вся операция может быть ускорена в несколько раз, просто путем сортировки данных перед их вставкой.С индексированием по хеш-таблице, поскольку вы не знаете заранее, какие ключи окажутся рядом друг с другом, эта оптимизация невозможна.

Обновление: я решил привести реальный пример.Он основан на следующем сценарии "db-test"

#!/usr/bin/perl
use warnings;
use strict;
use BerkeleyDB;
my %hash;
unlink "test.db";
tie %hash, (shift), -Filename=>"test.db", -Flags=>DB_CREATE or die;
while(<>) { $hash{$_}=1; }
untie %hash;

Мы можем протестировать его с помощью файла индекса дампа Википедии из 16 миллионов записей.(Я использую это на 800-МГц 2-ядерном ноутбуке с 3G-памятью)

$ >enw.tab bunzip2 <enwiki-20151102-pages-articles-multistream-index.txt.bz2
$ wc -l enw.tab
16050432 enw.tab
$ du -shL enw.tab
698M    enw.tab
$ time shuf enw.tab > test-shuf
  16.05s user 6.65s system 67% cpu 33.604 total
$ time sort enw.tab > test-sort
  70.99s user 10.77s system 114% cpu 1:11.47 total
$ time ./db-test BerkeleyDB::Btree < test-shuf
  682.75s user 368.58s system 42% cpu 40:57.92 total
$ du -sh test.db
1.3G    test.db
$ time ./db-test BerkeleyDB::Btree < test-sort
  378.10s user 10.55s system 91% cpu 7:03.34 total
$ du -sh test.db
923M    test.db
$ time ./db-test BerkeleyDB::Hash < test-shuf
  672.21s user 387.18s system 39% cpu 44:11.73 total
$ du -sh test.db
1.1G    test.db
$ time ./db-test BerkeleyDB::Hash < test-sort
  665.94s user 376.65s system 36% cpu 46:58.66 total
$ du -sh test.db
1.1G    test.db

Вы можете видеть, что предварительная сортировка клавиш Btree сокращает время вставки с 41 до 7 минут.Сортировка занимает всего 1 минуту, поэтому большой выигрыш - создание базы данных происходит в 5 раз быстрее.В формате Hash время создания одинаково медленно, независимо от того, отсортированы входные данные или нет.Также обратите внимание, что размер файла базы данных меньше для отсортированных вставок;по-видимому, это связано с балансировкой деревьев.

Ускорение должно быть из-за какого-то кеширования, но я не уверен, где.Вероятно, у нас меньше пропусков кэша в кэше страниц ядра с отсортированными вставками.Это согласуется с показателями использования ЦП - при пропадании кэша страницы процесс должен ждать, пока страница извлекается с диска, поэтому загрузка ЦП ниже.

Я провел те же тестыдля сравнения также с двумя меньшими файлами.

File       | WP index         | Wikt. words       | /usr/share/dict/words
Entries    | 16e6             | 4.7e6             | 1.2e5
Size       | 700M             | 65M               | 1.1M
shuf time  | 34s              | 4s                | 0.06s
sort time  | 1:10s            | 6s                | 0.12s
-------------------------------------------------------------------------
           | total  DB   CPU  |                   |
           | time  size  usage|                   |
-------------------------------------------------------------------------
Btree shuf | 41m,  1.3G, 42%  | 5:00s, 180M, 88%  | 6.4s, 3.9M, 86%
      sort | 7m,   920M, 91%  | 1:50s, 120M, 99%  | 2.9s, 2.6M, 97%
Hash  shuf | 44m,  1.1G, 39%  | 5:30s, 129M, 87%  | 6.2s, 2.4M, 98%
      sort | 47m,  1.1G, 36%  | 5:30s, 129M, 86%  | 6.2s, 2.4M, 94%
-------------------------------------------------------------------------
Speedup    | 5x               | 2.7x              | 2.2x

С самым большим набором данных, сортированные вставки дают нам 5-кратное ускорение.С наименьшим мы все равно получаем ускорение в 2 раза - даже если данные легко помещаются в память, так что загрузка процессора всегда высока.Похоже, это подразумевает, что мы извлекаем выгоду из другого источника эффективности в дополнение к кешу страниц, и что 5-кратное ускорение фактически было обусловлено равными частями кеша страниц и чем-то еще - возможно, лучшая балансировка дерева?В любом случае я предпочитаю формат Btree, потому что он позволяет выполнять более быстрые пакетные операции.Даже если конечная база данных доступна случайным образом, я использую пакетные операции для разработки, тестирования и обслуживания.Жизнь станет проще, если я найду способ ускорить их.

2 голосов
/ 09 ноября 2010

Это зависит от вашего набора данных и ключей. Для небольших наборов данных ваш тест будет близок к тому же, однако для больших наборов данных он может варьироваться в зависимости от того, какой тип ключей / сколько у вас данных.Обычно b-tree лучше, пока метаданные btree не превысят ваш кеш, и в итоге он выполнит много операций ввода-вывода, в этом случае хеш будет лучше.Кроме того, как вы указали, вставки b-дерева более дороги, если вы обнаружите, что вы будете делать много вставок и мало чтений, хеш может быть лучше, если вы обнаружите, что вы делаете небольшие вставки, но много операций чтения, b-дерево можетбыть лучше.

Если вы действительно обеспокоены производительностью, вы можете попробовать оба метода и запустить свои собственные тесты =]

0 голосов
/ 31 января 2015

Процитируем двух основных авторов Berkeley DB в это описание архитектуры:

Основное различие между методами доступа Btree и Hash заключается в том, что Btree предлагает локальность ссылок для ключей, а Hash - нет. это подразумевает, что Btree является правильным методом доступа практически ко всем данным наборы; тем не менее, метод доступа Hash подходит для наборов данных, так большой, что даже структуры индексации Btree не помещаются в память. В в этот момент лучше использовать память для данных, чем для индексации структур. Этот компромисс имел больше смысла в 1990 году, когда основной память обычно была намного меньше, чем сегодня.

Так что, возможно, во встроенных устройствах и специализированных случаях использования может работать хеш-таблица. BTree используется в современных файловых системах, таких как Btrfs , и это в значительной степени идеальная структура данных для создания баз данных или файловых систем.

...