![]() |
|
|||
WebMoney: WMZ Z294115950220 WMR R409981405661 WME E134003968233 |
Visa 4274 3200 2453 6495 |
Механизм по умолчанию, которым SQLite работает с дисковыми файлами базы
данных, это методы xRead() и xWrite() объекта VFS
sqlite3_io_methods.
Эти методы, как правило, осуществляются, как системные вызовы "read()" и
"write()", которые заставляют операционную систему копировать дисковое
содержание между ядерным кэш-буфером и пространством пользователя. Начиная с version 3.7.17
(2013-05-20), SQLite имеет выбор доступа к дисковому содержанию,
непосредственно используя I/O с отображенной памятью и новые методы
xFetch() и xUnfetch() в
sqlite3_io_methods. Есть преимущества и недостатки использования I/O с
отображенной памятью. Преимущества включают: Много операций, особенно интенсивно использующие средства
ввода-вывода, могут быть быстрее, так как содержание не должно быть
скопировано между ядерным пространством и пространством пользователя. Библиотеке SQLite, возможно, понадобится меньше RAM, так как это
поделится страницами с кэшем страницы операционной системы и не всегда
нуждается в собственной копии рабочих страниц. Но есть также недостатки: Ошибка I/O на файле с отображенной памятью не может быть
зафиксирована и имеет дело с SQLite. Вместо этого ошибка I/O вызывает сигнал,
который, если не пойман приложением, приводит к катастрофе программы. У операционной системы должен быть объединенный кэш-буфер для
расширения I/O с отображенной памятью, чтобы работать правильно, особенно в
ситуациях, где два процесса получают доступ к тому же самому файлу базы
данных, и один процесс использует I/O с отображенной памятью, в то время как
другой нет. Не у всех операционных систем есть объединенный кэш-буфер.
В некоторых операционных системах, которые утверждают, что имеют объединенный
кэш-буфер, внедрение глючное и может испортить базы данных. Производительность не всегда увеличивается с I/O с отображенной
памятью. На самом деле возможно построить тестовые сценарии, где она
уменьшается при помощи I/O с отображенной памятью. Windows неспособен усечь файл с отображенной памятью.
Следовательно, на Windows, если операция, такая как
VACUUM или
auto_vacuum,
пытается уменьшить размер файла базы данных с отображенной памятью, попытка
сокращения размера тихо потерпит неудачу, оставляя неиспользуемое место в
конце файла базы данных. Никакие данные не потеряны из-за этой проблемы, и
неиспользуемое место будет снова использовано снова в следующий раз, когда
база данных растет. Однако, если версия SQLite до 3.7.0 выполняет
PRAGMA integrity_check
на такой базе данных, это (неправильно) сообщит о повреждении
базы данных из-за неиспользуемого места в конце. Или если версия SQLite до
3.7.0 пишет базе данных, в то время как у нее все еще есть неиспользуемое
место в конце, это может сделать то неиспользуемое место недоступным
повторному использованию до окончания следующего
VACUUM. Из-за потенциальных недостатков I/O с отображенной памятью отключен по
умолчанию. Чтобы активировать I/O с отображенной памятью, используйте
mmap_size pragma
и установите mmap_size в некоторое большое количество, обычно 256 МБ или
больше, в зависимости от того, сколько адресного пространства ваше приложение
может сэкономить. Остальное автоматически.
PRAGMA mmap_size
будет тихо ничего не делать на системах, которые
не поддерживают I/O с отображенной памятью. Чтобы прочитать страницу содержания базы данных с использованием метода
xRead(), SQLite сначала ассигнует кусок размера страницы памяти кучи,
затем вызывает xRead(), который заставляет содержание страницы базы данных
быть скопированным в недавно ассигнованную память кучи. Это включает (как
минимум) копию всей страницы. Но если SQLite хочет получить доступ к странице файла базы данных, а
I/O с отображенной памятью позволен, это сначала вызывает метод xFetch().
Он просит, чтобы операционная система возвратила указатель на требуемую
страницу, если это возможно. Если требуемая страница была или может быть
отображена в прикладное адресное пространство, то xFetch возвращает указатель
на ту страницу для SQLite, чтобы использовать, не имея необходимость
копировать что-либо. Пропуск шага копии это то, что делает I/O с
отображенной памятью быстрее. SQLite не предполагает, что xFetch() будет работать. Если вызов xFetch()
вернет NULL (указание, что требуемая страница в настоящее время не
отображается в прикладное адресное пространство), тогда SQLite тихо отступает
к использованию xRead(). Об ошибке сообщают только, если xRead()
также терпит неудачу. Обновляя файл базы данных, SQLite всегда превращает копию содержания
страницы в память кучи прежде, чем изменить страницу.
Это необходимо по двум причинам. Во-первых, изменения базы данных, как
предполагается, невидимы другим процессам,
пока транзакция не передается и таким образом изменения должны произойти в
частной памяти. Во-вторых, SQLite использует карту постоянной памяти, чтобы
предотвратить случайные указатели в приложении от переписывания и разрушения
файла базы данных.
После того, как все необходимые изменения закончены, применяется xWrite(),
чтобы положить обратно содержание в файл базы данных.
Следовательно, использование I/O с отображенной памятью не изменяет
значительно исполнение изменений базы данных.
I/O с отображенной памятью главным образом выгодно для запросов. "mmap_size" это максимальное количество байтов файла базы данных, которое
SQLite попытается отобразить в адресное пространство процесса когда-то.
mmap_size применяется отдельно к каждому файлу базы данных, таким образом,
общая сумма адресного пространства процесса, которое могло потенциально
использоваться, является mmap_size умножить на
количество открытых файлов базы данных. Чтобы активировать I/O с отображенной памятью, приложение может установить
mmap_size в некоторое большое значение. Например: Чтобы отключить I/O с отображенной памятью, просто установите
mmap_size в ноль: Если mmap_size = N, все текущие внедрения отображают
первые N байт файла базы данных и используют xRead()
к любому содержанию вне N байт. Если файл базы данных меньше, чем N байт,
то весь файл отображен. В будущих, новых интерфейсах OS, в теории,
можно отобразить области файла кроме первых N байт, но никакое такое
внедрение в настоящее время не существует. mmap_size установлен отдельно для каждого файла базы данных, используя
"PRAGMA mmap_size".
Обычно умолчание mmap_size является нолем, означая, что I/O с отображенной
памятью отключен по умолчанию. Однако, умолчание mmap_size может быть
увеличено во время компиляции с использованием макроса
SQLITE_DEFAULT_MMAP_SIZE
или во время запуска, используя
sqlite3_config(
SQLITE_CONFIG_MMAP_SIZE,...). SQLite также поддерживает твердую верхнюю границу на mmap_size.
Попытки увеличить mmap_size выше этой твердой верхней границы (используя
PRAGMA mmap_size)
автоматически установят mmap_size к твердой верхней границе. Если твердая
верхняя граница ноль, то I/O с отображенной памятью невозможен.
Твердая верхняя граница может быть установлена во время компиляции,
используя макрос SQLITE_MAX_MMAP_SIZE
. Если SQLITE_MAX_MMAP_SIZE = 0,
то код, используемый, чтобы осуществить I/O с отображенной памятью, пропущен.
Твердая верхняя граница автоматически установлена в ноль на определенных
платформах (например, OpenBSD), где I/O с отображенной памятью не работает
из-за отсутствия объединенного кэш-буфера. Если твердая верхняя граница на mmap_size отлична
от нуля во время компиляции, это может все еще быть уменьшено или обнулено
во время запуска, используя
sqlite3_config(
SQLITE_CONFIG_MMAP_SIZE,X,Y). Параметры X и Y это 64-bit signed integer.
X задает mmap_size процесса, Y это новая твердая верхняя граница.
Твердая верхняя граница не может быть увеличена выше ее урегулирования
времени компиляции, используя
SQLITE_CONFIG_MMAP_SIZE, но может быть уменьшена или обнулена.
Choose any three.
I/O с отображенной памятью
Как I/O с отображенной памятью работает
Формирование I/O с отображенной памятью
PRAGMA mmap_size=268435456;
PRAGMA mmap_size=0;