| Примечание редактора: Данный документ был написан в 2004 году в качестве руководства для программистов, переходящих с SQLite2 на SQLite3. Он сохраняется как часть исторического архива SQLite. Современные программисты должны обращаться к более актуальной документации по SQLite, доступной на этом сайте. |
Обзор SQLite версии 3
SQLite версия 3.0 вносит важные изменения в библиотеку, включая:
- Более компактный формат файлов баз данных.
- Тип манифеста и поддержка BLOB.
- Поддержка UTF-8 и UTF-16 текста.
- Пользовательские последовательности сортировки текста.
- 64-битные ROWID.
- Улучшенная поддержка одновременного доступа.
Этот документ является кратким введением в изменения для SQLite 3.0 для пользователей, уже знакомых с SQLite версии 2.8.
Изменения имён
SQLite версия 2.8 будет продолжать поддерживаться с исправлениями ошибок в обозримом будущем. Для обеспечения мирного сосуществования SQLite версии 2.8 и SQLite версии 3.0 имена ключевых файлов и API в SQLite версии 3.0 были изменены с добавлением символа "3". Например, файл заголовков для C-программ был изменён с "sqlite.h" на "sqlite3.h". А имя программы командной строки для взаимодействия с базами данных было изменено с "sqlite.exe" на "sqlite3.exe". Благодаря этим изменениям можно одновременно установить как SQLite 2.8, так и SQLite 3.0 на одной системе. И одна и та же C-программа может подключаться к обеим версиям SQLite 2.8 и SQLite 3.0 одновременно и использовать обе библиотеки.
Новый формат файла
Формат, используемый файлами баз данных SQLite, был полностью переработан. Старый формат версии 2.1 и новый формат версии 3.0 несовместимы друг с другом. Версия 2.8 SQLite не будет читать файлы базы данных версии 3.0, и версия 3.0 SQLite не будет читать файлы базы данных версии 2.8.
Для преобразования базы данных SQLite 2.8 в базу данных SQLite 3.0 необходимо иметь оболочки командной строки для обеих версий 2.8 и 3.0. Затем введите команду, подобную следующей:
sqlite OLD.DB .dump | sqlite3 NEW.DB
Новый формат файлов баз данных использует B+ деревья для таблиц. В B+ дереве все данные хранятся в листьях дерева, а не как в обычном дереве, где данные хранятся и в листьях, и в промежуточных узлах. Использование B+ деревьев для таблиц обеспечивает лучшую масштабируемость и хранение больших полей данных без использования страниц переполнения. Традиционные B-деревья по-прежнему используются для индексов.
Новый формат файлов также поддерживает переменный размер страниц от 512 до 65536 байт. Размер страницы хранится в заголовке файла, поэтому одна и та же библиотека может читать базы данных с разными размерами страниц, теоретически, хотя эта функция пока не реализована на практике.
Новый формат файла исключает неиспользуемые поля из своих дисковых изображений. Например, индексы используют только ключевую часть записи B-дерева, а не данные. Таким образом, для индексов пропускается поле, записывающее длину данных. Целочисленные значения, такие как длина ключа и данных, хранятся с помощью кодирования переменной длины, так что для наиболее распространенных случаев требуется только один или два байта, но при необходимости может быть закодировано до 64 бит информации. Целые и вещественные данные хранятся на диске в двоичном формате, а не преобразуются в ASCII, как в SQLite версии 2.8. Эти изменения в совокупности приводят к файлам баз данных, которые обычно на 25% - 35% меньше, чем эквивалентные файлы в SQLite версии 2.8.
Подробные сведения о низкоуровневом формате B-дерева, используемом в SQLite версии 3.0, можно найти в комментариях к заголовкам файла btreeInt.h и в документации по формату файла.
Тип манифеста и поддержка BLOB
SQLite версия 2.8 работает с данными различных форматов в своей внутренней структуре, но при записи на диск или взаимодействии через API SQLite 2.8 всегда преобразует данные в текст ASCII. SQLite 3.0, в отличие от этого, предоставляет пользователю доступ к своим внутренним представлениям данных и хранит двоичные представления на диске, когда это уместно. Представление не-ASCII данных было добавлено для поддержки BLOB.
SQLite версия 2.8 имела функцию, позволяющую хранить любые типы данных в любом столбце таблицы независимо от объявленного типа этого столбца. Эта функция сохранена и в версии 3.0, хотя и в немного изменённой форме. Каждый столбец таблицы будет хранить любой тип данных, хотя столбцы имеют родство с форматом данных, определённым их объявленным типом данных. При вставке данных в столбец, столбец попытается преобразовать формат данных в объявленный тип столбца. Все SQL движки баз данных это делают. Разница в том, что SQLite 3.0 будет сохранять данные даже в случае, если преобразование формата невозможно.
Например, если у вас есть столбец таблицы, объявленный как "INTEGER", и вы пытаетесь вставить строку, столбец проверит текстовую строку и посмотрит, похожа ли она на число. Если строка выглядит как число, она преобразуется в число и в целое число, если число не имеет дробной части, и сохраняется таким образом. Но если строка не является корректным числом, она всё равно сохраняется как строка. Столбец с типом "TEXT" пытается преобразовать числа в представление ASCII-текста перед их сохранением. Но BLOB хранятся в столбцах TEXT как BLOB, потому что в общем случае нельзя преобразовать BLOB в текст.
В большинстве других SQL движков баз данных тип данных связан со столбцом таблицы, который хранит данные - с контейнером данных. В SQLite 3.0 тип данных связан с самими данными, а не с их контейнером. Пол Грэм в своей книге ANSI Common Lisp называет эту собственность "Манифестный тип". Другие авторы имеют другие определения термина "манифестный тип", так что будьте осторожны с путаницей. Но как бы вы его не называли, это модель типа данных, поддерживаемая SQLite 3.0.
Дополнительную информацию о типах данных в SQLite версии 3.0 можно найти отдельно.
Поддержка UTF-8 и UTF-16
Новый API для SQLite 3.0 содержит функции, которые принимают текст как UTF-8 и UTF-16 в родном байтовом порядке машины-хозяина. Каждый файл базы данных обрабатывает текст как UTF-8, UTF-16BE (большая эндианность) или UTF-16LE (малая эндианность). Внутренне и в файле на диске используется одно и то же представление текста. Если представление текста, указанное файлом базы данных (в заголовке файла), не соответствует представлению текста, необходимому для функций интерфейса, тогда текст преобразуется на лету. Постоянное преобразование текста из одного представления в другое может быть вычислительно дорогим, поэтому рекомендуется, чтобы программисты выбрали одно представление и придерживались его в своём приложении.
В текущей реализации SQLite синтаксический анализатор SQL работает только с текстом UTF-8. Поэтому, если вы предоставите текст UTF-16, он будет преобразован. Это всего лишь проблема реализации, и ничего не мешает будущим версиям SQLite обрабатывать SQL, закодированные в UTF-16, напрямую.
При создании новых пользовательских SQL функций и последовательностей сортировки каждая функция или последовательность сортировки может указать, работает ли она с UTF-8, UTF-16be или UTF-16le. Можно зарегистрировать отдельные реализации для каждого кодирования. Если требуется SQL функция или последовательность сортировки, но версия для текущего кодирования текста недоступна, текст автоматически преобразуется. Как и прежде, это преобразование занимает время вычислений, поэтому программистам рекомендуется выбрать одно кодирование и придерживаться его, чтобы свести к минимуму количество ненужного переформатирования.
SQLite не имеет особых требований к получаемому тексту и с удовольствием обрабатывает текстовые строки, которые не нормализованы или даже не являются правильно сформированными UTF-8 или UTF-16. Таким образом, программисты, которые хотят сохранить данные ISO8859, могут сделать это, используя интерфейсы UTF-8. До тех пор, пока не предпринимаются попытки использовать последовательность сортировки или SQL-функцию UTF-16, последовательность байтов текста не будет изменена никоим образом.
Пользовательские последовательности сортировки
Последовательность сортировки - это просто определённый порядок текста. Когда SQLite 3.0 сортирует (или использует оператор сравнения, например, "<" или ">=") порядок сортировки определяется типом данных.
- NULL сортируется первым
- Числовые значения сортируются дальше в числовом порядке
- Текстовые значения следуют за числовыми
- BLOB сортируются последними
Последовательности сортировки используются для сравнения двух текстовых строк. Последовательность сортировки не изменяет порядок NULL, чисел или BLOB, только текст.
Последовательность сортировки реализуется как функция, которая принимает две сравниваемые строки в качестве входных данных и возвращает отрицательное, нулевое или положительное значение, если первая строка меньше, равна или больше второй. SQLite 3.0 поставляется с одной встроенной последовательностью сортировки под названием "BINARY", которая реализована с помощью функции memcmp() из стандартной C библиотеки. Последовательность сортировки BINARY хорошо работает для английского текста. Для других языков или регионов могут быть предпочтительны альтернативные последовательности сортировки.
Решение о том, какую последовательность сортировки использовать, контролируется предложением COLLATE в SQL. Предложение COLLATE может присутствовать в определении таблицы, чтобы определить стандартную последовательность сортировки для столбца таблицы, или в поле индекса, или в предложении ORDER BY оператора SELECT. Планируется добавить в SQLite синтаксис стандартной функции CAST(), чтобы можно было задать последовательность сортировки выражения.
64-битные ROWID
Каждая строка таблицы имеет уникальный rowid. Если таблица определяет столбец с типом "INTEGER PRIMARY KEY", то этот столбец становится псевдонимом для rowid. Но есть или нет столбец INTEGER PRIMARY KEY, каждая строка всё равно имеет rowid.
В SQLite версии 3.0 rowid - 64-битное целое число со знаком. Это расширение SQLite версии 2.8, которая допускала только 32-битные rowid.
Для минимизации занимаемого места 64-битный rowid хранится как целое число переменной длины. Rowid от 0 до 127 используют только один байт. Rowid от 0 до 16383 используют всего 2 байта. До 2097152 используют три байта. И так далее. Разрешены отрицательные rowid, но они всегда используют 9 байт памяти, поэтому их использование не рекомендуется. Когда rowid генерируются автоматически SQLite, они всегда будут неотрицательными.
Улучшенная поддержка одновременного доступа
SQLite версия 2.8 позволяла несколько одновременных читателей или одного пишущего, но не оба одновременно. SQLite версия 3.0 позволяет одному процессу начать запись в базу данных, в то время как другие процессы продолжают чтение. Пишущий процесс всё равно должен получить эксклюзивную блокировку базы данных на короткий промежуток времени для фиксации изменений, но эксклюзивная блокировка больше не требуется для всей операции записи. Более подробная информация о поведении блокировок в SQLite версии 3.0 доступна отдельно.
Теперь в SQLite также доступна ограниченная форма блокировки на уровне таблиц. Если каждая таблица хранится в отдельном файле базы данных, эти отдельные файлы можно присоединить к основной базе данных (с помощью команды ATTACH), и объединённые базы данных будут работать как одна. Но блокировки будут приобретаться только на отдельных файлах по мере необходимости. Поэтому, если вы переопределите "базу данных", как два или более файлов базы данных, вполне возможно, что два процесса будут записывать в одну и ту же базу данных одновременно. Для дальнейшей поддержки этой возможности, фиксации транзакций, включающих две или более базы данных, присоединённые с помощью ATTACH, теперь являются атомарными.
Благодарности
SQLite версия 3.0 частично создана благодаря разработчикам AOL, поддерживающим и применяющим замечательное открытое программное обеспечение.
Эта страница была последний раз изменена 10.10.2023 17:29:48 UTC
SQLite is in the Public Domain.
https://sqlite.org/version3.html