Spec-Zone.ru › SQLite

Карта памяти Ввода/Вывода

По умолчанию SQLite использует методы xRead() и xWrite() объекта VFS sqlite3_io_methods для доступа к файлам базы данных и их обновления. Обычно эти методы реализуются как системные вызовы «read()» и «write()», которые заставляют операционную систему копировать содержимое диска между кэшем буферов ядра и пользовательским пространством.

Начиная с версии 3.7.17 (2013-05-20), SQLite имеет возможность прямого доступа к содержимому диска с помощью карты памяти Ввода/Вывода и новых методов xFetch() и xUnfetch() в объекте sqlite3_io_methods.

Использование карты памяти Ввода/Вывода имеет свои преимущества и недостатки. Преимущества включают:

  1. Многие операции, особенно ресурсоемкие операции Ввода/Вывода, могут быть быстрее, так как содержимое не нужно копировать между пространством ядра и пользовательским пространством.

  2. Библиотеке SQLite может потребоваться меньше оперативной памяти, так как она разделяет страницы с кэшем страниц операционной системы и не всегда нуждается в своей собственной копии рабочих страниц.

Но есть и недостатки:

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

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

  3. Производительность не всегда увеличивается при использовании карты памяти Ввода/Вывода. На самом деле, можно создать тестовые случаи, где использование карты памяти Ввода/Вывода снижает производительность.

  4. Windows не может обрезать файл, используемый с картой памяти. Следовательно, в Windows, если операция, такая как VACUUM или auto_vacuum пытается уменьшить размер файла базы данных с картой памяти, попытка уменьшить размер будет тихо проигнорирована, оставив неиспользуемое пространство в конце файла базы данных. Данные не теряются из-за этой проблемы, и неиспользуемое пространство будет повторно использовано при следующем увеличении базы данных. Однако, если версия SQLite до 3.7.0 выполняет PRAGMA integrity_check на такой базе данных, она (неправильно) сообщит о повреждении базы данных из-за неиспользуемого пространства в конце. Или если версия SQLite до 3.7.0 записывает в базу данных, пока в ней есть неиспользуемое пространство в конце, она может сделать это пространство недоступным для повторного использования до следующего VACUUM.

Из-за потенциальных недостатков карта памяти Ввода/Вывода отключена по умолчанию. Чтобы включить карту памяти Ввода/Вывода, используйте прагму mmap_size и установите mmap_size в большое число, обычно 256 МБ или больше, в зависимости от того, сколько адресного пространства вы можете освободить для приложения. Остальное выполняется автоматически. Вызов PRAGMA mmap_size будет молчаливой операцией бездействия на системах, которые не поддерживают карту памяти Ввода/Вывода.

Как работает карта памяти Ввода/Вывода

Для чтения страницы содержимого базы данных с помощью метода xRead(), SQLite сначала выделяет блок памяти размером страницы в куче, затем вызывает метод xRead(), который копирует содержимое страницы базы данных в только что выделенную память кучи. Это предполагает (как минимум) копирование всей страницы.

Но если SQLite хочет получить доступ к странице файла базы данных, а карта памяти Ввода/Вывода включена, она сначала вызывает метод xFetch(). Метод xFetch() просит операционную систему вернуть указатель на запрашиваемую страницу, если это возможно. Если запрашиваемая страница уже или может быть отображена в адресном пространстве приложения, то xFetch возвращает указатель на эту страницу для использования SQLite без необходимости копирования. Пропуск этапа копирования — то, что ускоряет карту памяти Ввода/Вывода.

SQLite не предполагает, что метод xFetch() будет работать. Если вызов xFetch() возвращает NULL-указатель (указывая, что запрашиваемая страница в данный момент не отображена в адресном пространстве приложения), то SQLite молча переходит к использованию xRead(). Ошибка будет сообщена только в случае, если xRead() также завершится ошибкой.

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

После завершения всех необходимых изменений используется xWrite() для возврата содержимого обратно в файл базы данных. Таким образом, использование карты памяти Ввода/Вывода не существенно изменяет производительность изменений в базе данных. Карта памяти Ввода/Вывода в основном приносит пользу для запросов.

Настройка карты памяти Ввода/Вывода

«mmap_size» — это максимальное количество байтов файла базы данных, которые SQLite попытается отобразить в адресном пространстве процесса одновременно. mmap_size применяется отдельно к каждому файлу базы данных, поэтому общее количество адресного пространства процесса, которое потенциально может быть использовано, равно mmap_size умноженному на количество открытых файлов базы данных.

Чтобы активировать карту памяти Ввода/Вывода, приложение может установить mmap_size в некоторое большое значение. Например:

PRAGMA mmap_size=268435456;

Чтобы отключить карту памяти Ввода/Вывода, просто установите mmap_size в ноль:

PRAGMA mmap_size=0;

Если mmap_size установлен в N, все текущие реализации отображают первые N байт файла базы данных и используют устаревшие вызовы xRead() для любого содержимого за пределами N байт. Если файл базы данных меньше N байт, то отображается весь файл. В будущем новые интерфейсы ОС теоретически могут отображать области файла, отличные от первых N байт, но такой реализации пока нет.

mmap_size устанавливается отдельно для каждого файла базы данных с помощью инструкции «PRAGMA mmap_size». Обычно значение mmap_size по умолчанию равно нулю, что означает, что карта памяти Ввода/Вывода отключена по умолчанию. Однако значение mmap_size по умолчанию можно увеличить либо во время компиляции, используя макрос SQLITE_DEFAULT_MMAP_SIZE, либо во время запуска, используя интерфейс sqlite3_config(SQLITE_CONFIG_MMAP_SIZE,...).

SQLite также поддерживает жёсткое верхнее ограничение на mmap_size. Попытки увеличить mmap_size выше этого жёсткого верхнего ограничения (с помощью PRAGMA mmap_size) автоматически ограничат mmap_size верхним пределом. Если жёсткое верхнее ограничение равно нулю, карта памяти Ввода/Вывода невозможна. Жёсткое верхнее ограничение может быть установлено во время компиляции с помощью макроса SQLITE_MAX_MMAP_SIZE. Если SQLITE_MAX_MMAP_SIZE установлен в ноль, то код, используемый для реализации карты памяти Ввода/Вывода, исключается из сборки. Жёсткое верхнее ограничение автоматически устанавливается в ноль на определённых платформах (например, OpenBSD), где карта памяти Ввода/Вывода не работает из-за отсутствия единого кэша буферов.

Если жёсткое верхнее ограничение на mmap_size ненулевое во время компиляции, оно всё равно может быть уменьшено или сведено к нулю во время запуска с помощью интерфейса sqlite3_config(SQLITE_CONFIG_MMAP_SIZE,X,Y). Параметры X и Y должны быть 64-битными целыми числами со знаком. Параметр X — это значение mmap_size процесса по умолчанию, а Y — новое жёсткое верхнее ограничение. Жёсткое верхнее ограничение не может быть увеличено выше значения при компиляции с помощью SQLITE_CONFIG_MMAP_SIZE, но может быть уменьшено или сведено к нулю.

SQLite is in the Public Domain.
https://sqlite.org/mmap.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API