Speichern Sie sie als ASCII-Zeichenfolge, und machen Sie das Feld zu einem Index.
EDIT
Egads, ich zufällig etwas Stossen über, und kam über das zu tun. Was für eine beschämende Antwort. Ich muss an diesem Tag in einer guten Laune gewesen sein. Wenn ich könnte, würde ich es einfach löschen und weitermachen. Dies ist jedoch nicht möglich, daher werde ich ein Update bereitstellen.
Erstens ist der einzige Weg zu wissen, was "effizient" ist, zu messen, unter Berücksichtigung von Programmzeit und -raum sowie der Komplexität des Quellcodes und des Programmieraufwands.
Glücklicherweise ist diese eine ziemlich einfach.
Ich schrieb eine sehr einfache OSX-Anwendung. Das Modell besteht aus einem einzigen Attribut: identifier
.
Nichts davon zählt, wenn Sie Ihr Attribut nicht als Index markieren. Es dauert viel mehr Zeit beim Erstellen des Geschäfts, aber es wird Abfragen viel schneller machen.
Beachten Sie auch, dass für ein binäres Attribut ein Prädikat schaffen, ist genau das gleiche wie eine für einen String zu erstellen:
fetchRequest.predicate =
[NSPredicate predicateWithFormat:@"identifier == %@", identifier];
Die Anwendung ist sehr einfach. Zuerst erstellt es N Objekte und weist dem Bezeichnerattribut eine UUID zu. Es speichert den MOC alle 500 Objekte. Wir speichern dann alle Identifikatoren in einem Array und mischen sie zufällig. Der gesamte CD-Stapel wird dann vollständig entfernt, um alles aus dem Speicher zu entfernen.
Als nächstes bauen wir den Stapel erneut, und dann über die Bezeichner iterieren und einen einfachen Abruf durchführen. Das Abrufobjekt wird mit einem einfachen Prädikat konstruiert, um dieses eine Objekt zu holen. All dies geschieht innerhalb eines Autorespulepools, um jeden Abruf so makellos wie möglich zu halten (ich bestätige, dass es eine Interaktion mit den CD-Caches geben wird). Das ist nicht so wichtig, da wir nur die verschiedenen Techniken vergleichen.
Binäre Kennung ist die 16-Byte für die UUID.
UUID Zeichenfolge ist eine 36-Byte-Zeichenfolge, das Ergebnis des Aufrufs von [UUID UUIDString], und es sieht so aus (B85E91F3-4A0A-4ABB-A049-83B2A8E6085E).
Base64 String ist eine 24-Byte-Zeichenfolge, das Ergebnis von Base-64 Codierung der 16-Byte-UUID-Binärdaten, und es sieht so (uF6R80oKSrugSYOyqOYIXg ==) für die gleiche UUID.
Anzahl ist die Anzahl der Objekte für diesen Lauf.
SQLite-Größe ist die Größe der tatsächlichen SQLite-Datei.
WAL Größe ist, wie groß die WAL (Write-Ahead-Logging-Datei) wird - gerade FYI ...
erstellen die Anzahl von Sekunden ist die Datenbank, einschließlich Einsparung zu erstellen.
Abfrage ist die Anzahl der Sekunden, um jedes Objekt abzufragen.
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
Das erste, was zu beachten ist hier, dass die tatsächliche Größe der Datenbank ist viel größer als der gespeicherten Bytes (1.600.000 und 16.000.000) - die für eine Datenbank zu erwarten ist. Die Menge an zusätzlichem Speicher ist etwas relativ zur Größe Ihrer tatsächlichen Objekte ... diese speichert nur die Kennung, so dass der Prozentsatz des Aufwands höher ist.
Zweitens, auf die Geschwindigkeit Probleme, als Referenz, die gleiche 1.000.000 Objektabfrage, aber mit der Objekt-ID in der Abruf dauerte etwa 82 Sekunden (beachten Sie den krassen Unterschied zwischen diesem und existingObjectWithID:error:
aufrufen, die satte 0,3065 Sekunden dauerte).
Sie sollten Ihre eigene Datenbank profilieren, einschließlich einer vernünftigen Verwendung von Instrumenten auf dem laufenden Code. Ich stelle mir vor, dass die Zahlen etwas anders sein würden, wenn ich mehrere Läufe machen würde, aber sie sind so nah, dass es für diese Analyse nicht notwendig ist.
Lassen Sie uns jedoch anhand dieser Zahlen Effizienzmessungen für die Codeausführung betrachten.
Wie erwartet, ist das Speichern der binären Roh-UUID-Daten in Bezug auf den Platz effizienter.
Die Erstellungszeit ist ziemlich nah (der Unterschied scheint auf der Zeit zu beruhen, die zum Erstellen der Zeichenfolgen und des zusätzlichen Speicherplatzes erforderlich ist).
Die Abfragezeiten scheinen fast identisch zu sein, wobei die Binärzeichenfolge ein wenig langsamer erscheint. Ich denke, das war das ursprüngliche Anliegen - eine Abfrage eines binären Attributs durchzuführen.
Binary gewinnt viel Platz, und es kann als ein enger Bezug sowohl zur Erstellungs- als auch zur Abfragezeit angesehen werden. Wenn wir nur diese betrachten, ist das Speichern der Binärdaten der klare Gewinner.
Wie wäre es mit Quellcode Komplexität und Programmierer Zeit?
Nun, wenn Sie eine moderne Version von iOS und OSX verwenden, gibt es praktisch keinen Unterschied, besonders mit einer einfachen Kategorie auf NSUUID.
Allerdings gibt es eine Überlegung für Sie, und das ist die Leichtigkeit der Verwendung der Daten in der Datenbank. Wenn Sie binäre Daten speichern, ist es schwierig, eine gute visuelle Darstellung der Daten zu erhalten.
Wenn also aus irgendeinem Grund die Daten in der Datenbank für Menschen effizienter gespeichert werden sollen, ist die Speicherung als Zeichenfolge die bessere Wahl. Sie sollten also eine base64-Kodierung (oder eine andere Kodierung) in Betracht ziehen - denken Sie daran, dass sie bereits in der Basis-256-Kodierung ist.
FWIW, hier ist ein Beispiel Kategorie einen leichteren Zugang zum UUID als sowohl NSData und Base64-String zur Verfügung zu stellen:
- (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;
}
Sie sich bewusst sind, dass der Zugang zu UDID ist haben als von iOS 5 als veraltet, nicht wahr? –
Das OP spricht über UUIDs, die sich von der UDID unterscheiden. –
@JodyHagins, Sie haben Recht. Die UUID, die ich erwähnte, ist Universally Unique IDentifier für ManagedObjects, die von meiner App erstellt werden. –