Персистентные функции хранилища

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

Типы хранилища и способы поведения

Базовые Данные обеспечивают три вида находящегося на диске персистентного хранилища — XML, атомарный, и SQLite — и хранилища в памяти. (Базовые Данные обеспечивают двоичный тип хранилища —NSBinaryStoreType— как встроенное атомарное хранилище; можно также создать собственные атомарные типы хранилища — посмотрите Пользовательские типы хранилища.) С точки зрения кода приложения в целом Вы не должны быть обеспокоены подробными данными реализации ни для какого определенного хранилища. Необходимо взаимодействовать с управляемыми объектами и штабелем персистентности. Существуют, однако, некоторые поведенческие различия между типами хранилища, которое необходимо рассмотреть при решении какой хранилище для использования.

XML

Атомарный

SQLite

В памяти

Скорость

Медленный

Быстро

Быстро

Быстро

Граф объектов

Целый

Целый

Частичный

Целый

Другие факторы

Внешне parseable

Никакая поддержка не требуется

Специфичное для хранилища поведение

Учитывая абстракцию, которую предлагают Базовые Данные, обычно нет никакой потребности использовать то же хранилище в течение процесса разработки. Распространено, например, использовать хранилище XML рано в жизненном цикле проекта, так как это довольно человекочитаемо, и можно проверить файл, чтобы определить, содержит ли это данные, которые Вы ожидаете. В развертываемом приложении, использующем большой набор данных, Вы обычно используете хранилище SQLite, так как это предлагает высокую производительность и не требует, чтобы весь граф объектов находился в памяти. Вы могли бы использовать двоичное хранилище, если Вы хотите, чтобы записи хранилища были атомарными. Существуют, однако, некоторые функции и соображения, которые являются определенными для определенных типов хранилища. Они описаны в следующих разделах.

Пользовательские типы хранилища

В OS X v10.5 и позже можно создать собственные атомарные типы хранилища. Для получения дополнительной информации посмотрите, что Атомарное Хранилище Программирует Темы.

В OS X v10.4, Вы не можете записать свою собственную объектно-ориентированную память, взаимодействующую прозрачно с Базовым Стеком данных. Можно, однако, управлять объектной персистентностью сами при помощи хранилища в памяти. Перед загрузкой данных Вы создаете хранилище в памяти. При загрузке данных Вы создаете экземпляры надлежащих классов модели и вставляете их в контекст управляемого объекта, связываете их с хранилищем в памяти (см. insertObject: и assignObject:toPersistentStore:). Управляемые объекты тогда полностью интегрируются в Базовый Стек данных и преимущество от функций, таких как управление отменой. Вы также ответственны, однако, для того, чтобы сохранить данные. Необходимо зарегистрироваться для получения NSManagedObjectContextDidSaveNotification уведомления от контекста управляемого объекта, и по получении уведомления сохраняют управляемые объекты к персистентному хранилищу.

Безопасность

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

Предикаты выборки и дескрипторы вида

Существуют некоторые взаимодействия между выборкой и типом хранилища. В XML, двоичном файле и хранилищах в памяти, оценка предиката и дескрипторов вида выполняется в Objective C с доступом к функциональности всего Какао, включая методы сравнения для NSString. Хранилище SQL, с другой стороны, компилирует предикат и дескрипторы вида к SQL и оценивает результат в самой базе данных. Это сделано прежде всего для производительности, но это означает, что оценка происходит в среде некакао, и так дескрипторы вида (или предикаты), которые полагаются на Какао, не может работать. Поддерживаемые селекторы вида compare: и caseInsensitiveCompare:, localizedCompare:, localizedCaseInsensitiveCompare:, и localizedStandardCompare: (последний является подобной Средству поиска сортировкой, и что большинство людей должно использовать большую часть времени). Кроме того, Вы не можете сортировать на переходных свойствах с помощью хранилища SQLite.

Существуют дополнительные ограничения на предикаты, которые можно использовать с хранилищем SQLite:

- CoreData поддерживает noindex: (см. ре документации NSPredicate: выражения function), который может использоваться для отбрасывания индексов в запросах, переданных SQLite. Это сделано прежде всего по причинам производительности: SQLite использует ограниченное количество индексов на запрос и noindex: позволяет пользователю предпочтительно указывать, какие индексы не должны использоваться.

Хранилище SQLite

Файловые системы поддерживаются хранилищем SQLite

SQLite хранят поддержки, читая данные из файла, находящегося на любом типе файловой системы. Хранилище SQLite в целом, однако, не поддерживает запись непосредственно в файловые системы, не реализующие блокировку диапазона байта. Для файловых систем DOS и для некоторых реализаций файловой системы NFS, не поддерживающих диапазон байта, блокирующий правильно, SQLite будет использовать» <dbfile> .lock» блокировка, и для файловых систем SMB это использует блокировку стиля скопления.

Подводить итог: диапазон байта, блокирующий файловые системы, имеет лучшую параллельную поддержку чтения-записи; они включают HFS +, AFP и NFS. Файловые системы с упрощенным захватом файла также поддерживаются, но не допускают столько же параллельного доступа для чтения-записи многократными процессами; они включают SMB и DOS. Хранилище SQLite не поддерживает запись в файловые системы WebDAV (это включает iDisk).

Размер файла может не сократить после удаления записи

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

Файл SQLite располагается как набор страниц. Данными в тех страницах управляют через B-деревья, не как простые записи фиксированной длины. Это намного более эффективно для поиска и для полного хранения, так как это позволяет SQLite оптимизировать, как это хранит и данные и индексирует в единственном файле и является также основой его целостности данных (транзакция и журналирующий) механизм. Однако стоимость этого - то, что некоторые удаляют операции, может покинуть дыры в файле. Если Вы удаляете некоторые данные и добавляете другие данные, дыры, покинутые удаленными данными, могут быть заполнены добавленными данными, или файл может пропылесоситься для уплотнения его данных, какой бы ни SQLite считает самым надлежащим на основе операций, которые Вы выполняете.

Конфигурирование поведения сохранения хранилища SQLite

Когда Базовые Данные сохраняют хранилище SQLite, обновления SQLite просто часть файла хранилища. Потеря того частичного обновления была бы катастрофической, таким образом, можно хотеть гарантировать, что файл записан правильно, прежде чем приложение продолжается. К сожалению, выполнение так означает, что в некоторых ситуациях, сохраняющих даже маленький набор изменений в хранилище SQLite, может взять значительно дольше, чем сохранение к, скажем, хранилищу XML. (Например, где сохранение к XML-файлу могло бы взять меньше чем одну сотую секунды, сохранение к хранилищу SQLite может занять почти половину секунды. Это не проблема для XML или Двоичных хранилищ — так как они являются атомарными, существует намного более низкая вероятность потери данных, включающей повреждение файла, тем более, что записи являются обычно атомарными, и старый файл не удален, пока новое не было успешно записано.)

Базовые Данные обеспечивают способ управлять синхронизирующим поведением в SQLite использование двух независимых прагм, давая Вам контроль над компромиссом между производительностью и надежностью:

  • synchronous управляет частотой синхронизации диска

    PRAGMA synchronous FULL [2] / NORMAL [1] / OFF [0]

  • full_fsync управляет типом синхронизирующей диском выполняемой работы

    PRAGMA fullfsync 1 / 0

    В OS X v10.5, значение по умолчанию 0.

Прагмы публично документируются в http://sqlite .org/pragma.html.

Можно установить обе прагмы с помощью ключа NSSQLitePragmasOption в словаре опций при открытии хранилища. NSSQLitePragmasOption словарь содержит имена прагмы как ключи и строковые значения как объекты, как проиллюстрировано в следующем примере:

NSPersistentStoreCoordinator *psc = <#Get a persistent store coordinator#>;
 
NSMutableDictionary *pragmaOptions = [NSMutableDictionary dictionary];
[pragmaOptions setObject:@"NORMAL" forKey:@"synchronous"];
[pragmaOptions setObject:@"1" forKey:@"fullfsync"];
 
NSDictionary *storeOptions =
    [NSDictionary dictionaryWithObject:pragmaOptions forKey:NSSQLitePragmasOption];
NSPersistentStore *store;
NSError *error = nil;
store = [psc addPersistentStoreWithType:NSSQLiteStoreType
            configuration: nil
            URL:url
            options:storeOptions
            error:&error];