2012-07-05 2 views
13

Я ищу эффективный способ хранения и поиска UUID в Core Data. Эти UUID генерируются многими устройствами iOS в распределенной системе. Каждое из этих устройств может хранить около 20-50 тыс. UUID.Как эффективно вставлять и извлекать UUID в базовых данных

Очевидно, что сохранение UUID в виде строки в базовых данных может повредить эффективность индексации на нем. Но после серии исследований я обнаружил, что сохранение UUID в виде двоичных данных в основных данных (и индексация) может быть менее эффективным, чем сохранение его как String.

Поскольку в SQLit не поддерживается тип данных BINARY или VARBINARY. Я предполагаю, что любой тип данных двоичных данных в Core Data хранится как BLOB в SQLit. Поскольку BLOB может быть самым медленным типом данных, который будет проиндексирован, это может оказать плохое влияние на производительность.

Может ли кто-нибудь помочь ответить, есть ли более эффективный способ хранения UUID в Core Data?

+0

вы знаете, что доступ к UDID были устаревшим прошивкой 5, да? –

+3

OP говорит о UUID, которые отличаются от UDID. –

+0

@JodyHagins, вы правы. UUID, о котором я упоминал, является универсальным уникальным идентификатором для ManagedObjects, созданным моим приложением. –

ответ

30

Сохраните их как строку ASCII и сделайте поле индексом.

EDIT

Egads, я случайно делать некоторые тыкать о, и наткнулся на это. Какой позорный ответ. В тот день, должно быть, у меня было настроение. Если бы я мог, я бы просто удалил его и продолжил. Тем не менее, это невозможно, поэтому я расскажу об обновлении.

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

К счастью, этот довольно прост.

Я написал очень простое приложение OSX. Модель состоит из одного атрибута: identifier.

Ничего из этого не имеет значения, если вы не отмечаете свой атрибут как индекс. При создании магазина потребуется гораздо больше времени, но он будет делать запросы намного быстрее.

Кроме того, обратите внимание, что при создании предиката для бинарного атрибута является точно такой же, как создание одного для строки:

fetchRequest.predicate = 
    [NSPredicate predicateWithFormat:@"identifier == %@", identifier]; 

Приложение очень просто. Во-первых, он создает N объектов и присваивает UUID атрибуту идентификатора. Он сохраняет MOC каждые 500 объектов. Затем мы сохраняем все идентификаторы в массив и произвольно перетасовываем их. Затем весь CD-стоп полностью разорван, чтобы удалить все из памяти.

Затем мы снова создаем стек, а затем перебираем идентификаторы и делаем простую выборку. Объект fetch построен с простым предикатом для извлечения этого одного объекта. Все это делается внутри autoreleasepool, чтобы каждый выбор был как можно более чистым (я признаю, что будет некоторое взаимодействие с кэшами CD). Это не так важно, поскольку мы просто сравниваем разные методы.

Двоичный идентификатор - это 16-байты для UUID.

UUID String - это 36-байтовая строка, результат вызова [uuid UUIDString], и это выглядит так (B85E91F3-4A0A-4ABB-A049-83B2A8E6085E).

Base64 String - это 24-байтовая строка, в результате которой базовый 64 кодирует 16-байтовые двоичные данные UUID, и он выглядит так (uF6R80oKSrugSYOyqOYIXg ==) для того же UUID.

Count - количество объектов для этого запуска.

Размер SQLite - это размер фактического файла sqlite.

WAL размер как большой получает файл WAL (с упреждением каротаж) - просто FYI ...

Создать это количество секунд, чтобы создать базу данных, в том числе экономии.

Запрос - это количество секунд для запроса каждого объекта.

Data Type  | Count (N) | SQLite Size | WAL Size | Create | Query 
--------------+-----------+-------------+-----------+---------+--------- 
Binary  | 100,000 | 5,758,976 | 5,055,272 | 2.6013 | 9.2669 
Binary  | 1,000,000 | 58,003,456 | 4,783,352 | 59.0179 | 96.1862 
UUID String | 100,000 | 10,481,664 | 4,148,872 | 3.6233 | 9.9160 
UUID String | 1,000,000 | 104,947,712 | 5,792,752 | 68.5746 | 93.7264 
Base64 String | 100,000 | 7,741,440 | 5,603,232 | 3.0207 | 9.2446 
Base64 String | 1,000,000 | 77,848,576 | 4,931,672 | 63.4510 | 94.5147 

Первое, что нужно отметить, что фактический размер базы данных намного больше, чем байт сохраняемое (1600000 и 16000000) - что можно ожидать для базы данных. Объем дополнительного хранилища будет несколько относительно размера ваших реальных объектов ... этот хранит только идентификатор, поэтому процент накладных расходов будет выше).

Во-вторых, по вопросам скорости, для справки, выполнение одного и того же 1,000 000 объектного запроса, но с использованием идентификатора объекта в выборке потребовалось около 82 секунд (обратите внимание на резкую разницу между этим и вызовом existingObjectWithID:error:, который занял колоссальные 0,3065 секунды).

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

Однако, исходя из этих чисел, давайте посмотрим на измерения эффективности для выполнения кода.

  • Как и ожидалось, сохранение исходных двоичных данных UUID более эффективно с точки зрения пространства.
  • Время создания довольно близко (различие, по-видимому, зависит от времени создания строк и дополнительного пространства для хранения).
  • Времена запроса кажутся почти идентичными, при этом двоичная строка выглядит немного медленнее. Я думаю, что это была первоначальная проблема - выполнение запроса по двоичному атрибуту.

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

Как насчет сложности исходного кода и времени программиста?

Хорошо, если вы используете современную версию iOS и OSX, практически нет разницы, особенно с простой категорией на NSUUID.

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

Итак, если по какой-то причине вы хотите, чтобы данные в базе данных были сохранены более эффективным образом для людей, то сохранение его в виде строки является лучшим выбором. Таким образом, вы можете рассмотреть кодировку base64 (или некоторую другую кодировку, хотя помните, что она уже находится в кодировке base-256).

FWIW, вот пример категории, чтобы обеспечить легкий доступ к UUID как оба NSData и base64 строки:

- (NSData*)data 
{ 
    uuid_t rawuuid; 
    [self getUUIDBytes:rawuuid]; 
    return [NSData dataWithBytes:rawuuid length:sizeof(rawuuid)]; 
} 

- (NSString*)base64String 
{ 
    uuid_t rawuuid; 
    [self getUUIDBytes:rawuuid]; 
    NSData *data = [NSData dataWithBytesNoCopy:rawuuid length:sizeof(rawuuid) freeWhenDone:NO]; 
    return [data base64EncodedStringWithOptions:0]; 
} 

- (instancetype)initWithBase64String:(NSString*)string 
{ 
    NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0]; 
    if (data.length == sizeof(uuid_t)) { 
     return [self initWithUUIDBytes:data.bytes]; 
    } 
    return self = nil; 
} 

- (instancetype)initWithString:(NSString *)string 
{ 
    if ((self = [self initWithUUIDString:string]) == nil) { 
     self = [self initWithBase64String:string]; 
    } 
    return self; 
} 
+0

Хороший совет, спасибо. Это может сэкономить половину усилий для Core Data. Но мне все еще интересно, как строка ASCII отображается из Core Data в SQLit. Я предполагаю, что только реальный тест может сказать. –

+0

В общем, вы хотите убедиться, что любые строки, которые вы выполняете, нормализуются, чтобы исключить юникод. Кроме того, вместо использования запросов, нечувствительных к регистру, нормализуйте данные для удаления unicode и case. Используйте < and > вместо BEGINSWITH и т. Д. В видеороликах 2010, 2011 и 2012 годов есть отличные предложения. Я настоятельно рекомендую их. –

+0

hi @JodyHagins Не могли бы вы указать имена видео WWDC по этой теме. Их слишком много. Заранее спасибо. –

Смежные вопросы