Эффективное хранение идентичных данных в базовой модели данных


У меня есть модель данных, которая содержит несколько сущностей, каждая из которых имеет несколько различных атрибутов, хранящих данные изображения. Все это будут небольшие изображения, и мне нужно хранить их в постоянном хранилище, а не как внешние файлы.

Хотя я могу просто хранить данные изображения в двоичном или трансформируемом атрибуте, вполне вероятно, что пользователь укажет идентичные изображения для двух или более из этих атрибутов, поэтому я предпочел бы хранить одну копию каждого уникального изображения, а не дублировать данные изображения.

Я возился с созданием сущности "ImageBlob" для хранения данных изображения и использования отношений для этого, но я новичок с основными данными, и мне не сразу ясно, правильный ли это путь. В частности, как я справляюсь со следующими ситуациями?

  • я хочу, чтобы все мои атрибуты изображений в нескольких сущностях использовали одно и то же "хранилище данных изображений", чтобы сохранялся только один экземпляр каждого большого двоичного объекта изображения
  • мне нужно убедиться, что что если никакие объекты не используют изображение в хранилище данных, то оно удаляется

Как лучше всего с этим справиться?

2 4

2 ответа:

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

Однако, если у вас есть способ сделать это эффективно, вы можете создать сущность ImageBlob, чтобы сделать то, что вы описываете. То сущность, использующая ImageBlobs, должна иметь отношение 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.