Эффективное хранение идентичных данных в базовой модели данных
У меня есть модель данных, которая содержит несколько сущностей, каждая из которых имеет несколько различных атрибутов, хранящих данные изображения. Все это будут небольшие изображения, и мне нужно хранить их в постоянном хранилище, а не как внешние файлы.
Хотя я могу просто хранить данные изображения в двоичном или трансформируемом атрибуте, вполне вероятно, что пользователь укажет идентичные изображения для двух или более из этих атрибутов, поэтому я предпочел бы хранить одну копию каждого уникального изображения, а не дублировать данные изображения.
Я возился с созданием сущности "ImageBlob" для хранения данных изображения и использования отношений для этого, но я новичок с основными данными, и мне не сразу ясно, правильный ли это путь. В частности, как я справляюсь со следующими ситуациями?
- я хочу, чтобы все мои атрибуты изображений в нескольких сущностях использовали одно и то же "хранилище данных изображений", чтобы сохранялся только один экземпляр каждого большого двоичного объекта изображения
- мне нужно убедиться, что что если никакие объекты не используют изображение в хранилище данных, то оно удаляется
Как лучше всего с этим справиться?
2 ответа:
Мой первый вопрос: как вы планируете идентифицировать, когда два объекта используют одно и то же изображение? Есть ли свойство на изображении, которое вы можете сохранить и запросить, чтобы определить, существует ли уже заданное изображение? И насколько это дорого с точки зрения вычислений? Если это займет много времени, вы можете в конечном итоге оптимизировать хранилище и повлиять на производительность.
Однако, если у вас есть способ сделать это эффективно, вы можете создать сущностьImageBlob
, чтобы сделать то, что вы описываете. То сущность, использующаяImageBlob
s, должна иметь отношениеimageBlob
илиimageBlobs
сImageBlob
.ImageBlob
должно иметь обратную связь с именем, например,users
.В вашем коде, когда вы хотите повторно использовать
ImageBlob
, это так же просто, как сделать что-то вроде этого:Еще одно соображение, о котором вы захотите подумать, - что делать с каплями, которые больше не нужны. Предположительно, вы хотите удалить все изображения, которые не используются. Для этого вы можете зарегистрировать свое приложение делегировать или подклассNSManagedObject *blob = // get the image blob NSManagedObject *user = // get the user [user setValue:blob forKey:@"imageBlob"]; // do this if it uses a single image [[user mutableSetValueForKey:@"imageBlobs"] addObject:blob]; // do this if it uses multiple images
NSPersistentDocument
(в зависимости от того, основано ли ваше приложение на документе или нет) для уведомленияNSManagedObjectContextObjectsDidChangeNotification
. При изменении контекста управляемого объекта можно удалить все ненужные изображения, например:- (void)managedObjectContextObjectsDidSave:(NSNotification *)notification { NSManagedObjectContext *managedObjectContext = [notification object]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:[NSEntity entityWithName:@"ImageBlob" inManagedObjectContext:managedObjectContext]]; [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"users.@count == 0"]; NSArray *unusedBlobs = [managedObjectContext executeFetchRequest:fetchRequest error:nil]; // Don't be stupid like me; catch and handle the error [fetchRequest release]; for (NSManagedObject *blob in unusedBlobs) { [managedObjectContext deleteObject:blob]; } }
Вы можете добавить уникальное свойство md5 к сущности
Image
, чтобы убедиться, что вы храните одни и те же изображения только один раз.Что касается основных данных, я думаю, что-то вроде этого может сработать.: Затем создайте абстрактную родительскую сущность (
Parent
). Добавьте отношение изParent
вImage
, называемоеimage
, и установите "каскад" для метода удаления, чтобы при удаленииParent
,Image
также удаляется. Добавьте отношение изImage
вParent
, называемоеparent
, или что угодно, и установите "Nullify" для метод удаления таким образом, чтобы при удаленииImage
изображение дляParent
было установлено вnil
. Затем добавьте другие сущности и задайте для их родителя значениеParent
.