Структура базы данных и жесткий диск ищут путаницу времени - PullRequest
3 голосов
/ 01 марта 2009

может кто-нибудь помочь мне, пытаясь понять, как работает поиск на жестком диске.

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

Если среднее время поиска жесткого диска составляет 10 мс, а скорость чтения составляет 300 МБ / с, я подсчитал, что читать () быстрее, чем поиск () со значением меньше 3 МБ. Правда? Есть ли издержки при выполнении нового поиска, которого нет при чтении существующего потока?

Какая структура файла подходит для индекса?

Entry1:Value:PointerIntoToData
Entry2:Value:PointerIntoToData
Entry3:Value:PointerIntoToData
Data, Data, Data

Or

Entry1:Value:Data
Entry2:Value:Data
Entry3:Value:Data

При чтении записи, если значение неверно, оно будет проигнорировано. Так что при потоковой передаче файла это быстрее: 1. когда запись не требуется, используйте seek (), чтобы пропустить ее 2. если запись не нужна, прочитайте ее, затем отбросьте данные 3. или использовать первую структуру, когда в конце требуется запись seek () в хранилище данных.

Запись 4 байта, значение 8 байтов и данные 12 КБ

Приветствия

Ответы [ 4 ]

4 голосов
/ 02 марта 2009

Все seek , которые выполняет системный вызов, изменяет позицию в файле, где будет следующее чтение. Он не двигает головку привода. Головки дисков перемещаются, когда данные читаются или записываются, и у вас нет прямого контроля над тем, что будет делать следующая ОС.

Чтение большого количества данных, которые вам не нужны, оказывает влияние, поскольку все считанные данные требуют пространства в буферах ОС и приводят к удалению старых данных. Поэтому использование поиска по большим файлам будет меньше мешать кешу файловой системы.


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


Если ваша база данных слишком велика:

Данные читаются и записываются на физический диск блоками (или страницами). Точно так же основной единицей дискового ввода-вывода в вашей ОС является страница. Если ОС кеширует данные с диска, то это также целые страницы. Поэтому думать, нужно ли вам двигаться вперед на несколько байтов, используя поиск или чтение, не имеет большого смысла. Если вы хотите сделать это быстро, вы должны принять во внимание, как действительно работает дисковый ввод-вывод.

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

Что касается структуры данных для индекса. Обычно они организованы как B-деревья . Это структура данных, созданная специально для эффективного поиска больших объемов данных, хранящихся в памяти, с постраничными операциями чтения и записи.

И обе стратегии организации данных используются на практике. Например, MS SQL Server по умолчанию хранит данные первым способом: данные хранятся отдельно, а индексы содержат только данные из проиндексированных столбцов и физические адреса строк данных в файлах. Но если вы определите кластерный индекс, то все данные будут храниться в этом индексе. Все остальные индексы будут указывать на данные через ключ кластеризованного индекса вместо физического адреса. Первый способ проще, но другой может быть гораздо эффективнее, если вы часто сканируете диапазоны данных на основе кластерного индекса.

3 голосов
/ 01 марта 2009

Насколько «абсолютно необходим» поиск доступа? Вы уже протестировали свое приложение с неоптимальным решением? В ходе этого теста вы тестировали, чтобы определить узкие места real ? Если нет, вы будете удивлены результатами.

Далее попробуйте разные методы и сравните время выполнения. Тестируйте при разных нагрузках системы (т. Е. Когда система простаивает, за исключением вашего приложения и когда она занята).

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

1 голос
/ 01 марта 2009

Последовательное чтение всегда выполняется быстрее, чем при поиске по голове (не по позиции). Типичная производительность жесткого диска для последовательного чтения составляет 50-60 МБ / с, что позволяет уменьшить скорость до наихудшего случая ~ 0,4 МБ / с. Как только головки привода расположены, вы по существу получаете данные в цилиндре бесплатно. Кэш файловой системы использует это преимущество, предварительно считывая секторы из цилиндра.

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

0 голосов
/ 02 марта 2009

Вы всегда можете отобразить файл в память, а затем получить к нему доступ через указатели и тому подобное. Это, как правило, должно сделать ваш доступ проще и быстрее.

...