2017-02-09 9 views
0

Я пытаюсь выполнить массивную вставку данных в Realm, но это делает ее очень медленной.Как вставить много записей в Realm с Swift?

Это мой код:

let realm = try! Realm() 


let group = GroupRealm() 

group.id = 1 
group.name = "test" 

try! realm.write { 
    realm.add(group) 
} 

var product = [String:AnyObject]() 
product["id"] = "" as AnyObject! 
product["code"] = ("") as AnyObject! 
product["detail"] = ("") as AnyObject! 
product["onHand"] = (0) as AnyObject! 
product["price"] = (0) as AnyObject! 
product["isSerialized"] = (0) as AnyObject! 
product["isLotNumber"] = (0) as AnyObject! 

var groupProduct = [String:AnyObject]() 
groupProduct["group"] = group as AnyObject! 

for r in 0..<300 { 
    realm.beginWrite() 
    for i in 0..<100 { 
     product["id"] = "\(i)-\(r)" as AnyObject! 
     realm.create(ProductRealm.self, value: product, update: true) 

     groupProduct["id"] = "\(i)-\(r)" as AnyObject! 
     groupProduct["product"] = product as AnyObject! 
     realm.create(GroupProductRealm.self, value: groupProduct, update: true) 
    } 
    try! realm.commitWrite() 
} 

Объекты:

class ProductRealm: Object { 
    public dynamic var id: String = "" 
    public dynamic var code: String = "" 
    public dynamic var detail: String = "" 
    public dynamic var onHand: Int = 0 
    public dynamic var price: Double = 0 
    public dynamic var isSerialized: Int = 0 
    public dynamic var isLotNumber: Int = 0 
    override static func primaryKey() -> String? { 
     return "id" 
    } 
} 

class GroupProductRealm: Object { 
    public dynamic var id = "" 
    public dynamic var group: GroupRealm! 
    public dynamic var product: ProductRealm! 
    override static func primaryKey() -> String? { 
     return "id" 
    } 
} 
class GroupRealm: Object { 
    public dynamic var id = 1 
    public dynamic var name = "" 
    public dynamic var update = Date() 
    override static func primaryKey() -> String? { 
     return "id" 
    } 
} 

Испытания на моем iPhone 5s для вставки 30000 записей задерживается более чем на 30 секунд, в то время как в старом проекте у меня есть с sqlite требуется около 16 секунд.

Я прочитал, что сфера гораздо быстрее, чем в этом SQLite, так что я знаю, что это ошибка моя, но я не даю с D:

Извините за мой английский.

+1

Почему вы делаете на операции записи в отдельных 300 операций записи, а не в одной транзакции записи? – bdash

+0

У меня есть код для отображения счетчика каждый раз, когда вы вставляете 100 записей, и проверяете время с и без этой части кода, и оно не сильно влияет на –

+0

Испытание с 30000 в одной транзакции. Время: 25 секунд –

ответ

0

Мой уровень английского языка не очень высок, поэтому я опубликую код с комментариями на испанском языке, если кто-то может изменить его, чтобы быть на английском языке. Я был бы признателен.

https://es.stackoverflow.com/questions/48676/como-insertar-muchos-registros-en-realm-con-swift/48913#48913

// 
// ViewController.swift 
// TestRealm 
// 
// Created by Sergio Castro on 10/02/17. 
// Copyright © 2017 BasTechSoluctions. All rights reserved. 
// 

import UIKit 
import RealmSwift 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Mostrar la ubicación del proyecto para ubicar la base de datos 
     print(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.absoluteString) 


     DispatchQueue(label: "background").async { //Abrir un nuevo hilo para insertar de forma asíncrona 
      autoreleasepool { 

       let date1 = Date() // Inicia el conteo del tiempo 

       let realm = try! Realm() // Instanciar realm en el hilo nuevo 

       let products = realm.objects(ProductRealm.self) //Crear una lista de todos los productos 

       //Crear grupo 
       let group = GroupRealm() 
       group.id = 1 
       group.name = "test" 

       try! realm.write { //Insertar/Reemplazar grupo, sin productos 
        realm.create(GroupRealm.self, value: group, update: true) 
       } 

       ///Crear json 
       //Primero creo un String, donde ingreso todos los datos en formato [{},{},...] 
       var stringJson = "[" 
       for i in 0..<30000 { 
        if(i > 0){ stringJson.append(",") } 
        let dataOrigin = "{\"id\": \"\(i)\", \"code\": \"\", \"detail\": \"\", \"onHand\": 0, \"price\": 0, \"isSerialized\": 0, \"isLotNumber\": 0}" 
        stringJson.append("\(dataOrigin)") 
       } 
       stringJson.append("]") 

       //Convertir el String en Datos y luego pasarlo a jsonObject (esto para simular el proceso de descarga de datos) 
       let data = stringJson.data(using: .utf8)! 
       let jsonP = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [Any] 

       //Mostrar el tiempo empleado para la creación del json en consola, el tiempo está en segundos por defecto 
       let date2 = Date() 
       var time = date2.timeIntervalSince(date1) 
       print("Json creation in seconds \(time)") 

       //Recorrer el json en grupos de 100, tantas veces haga falta para recorrer por completo el json, en este caso 300 veces 
       let limit = 100 
       for c in 0..<(jsonP.count/limit){ 
        //Insertar/Reemplazar los grupos de datos 
        realm.beginWrite() 
        for i in 0..<limit{ 
         let row = jsonP[i + (c*limit)] 
         realm.create(ProductRealm.self, value: row, update: true) 
        } 
        try! realm.commitWrite() 
        //Mostrar en consola la cantidad de procesos realizados vs la cantidad de registros actuales 
        ///print("\((c+1)*limit)/\(products.count)") //Este proceso aumenta el tiempo de cálculo 
        print("\((c+1)*limit)") //Este proceso no afecta mucho el tiempo de cálculo 
       } 

       group.products.append(objectsIn: products) //Agregar los productos al grupo, aquí se pueden poner filtros 

       //Actualizar el grupo, para que el array products tenga una referencia a sus productos correspondientes 
       try! realm.write { 
        realm.create(GroupRealm.self, value: group, update: true) 
       } 

       // Calcular el tiempo de inserción y mostrarlo en consola 
       let date3 = Date() 
       time = date3.timeIntervalSince(date2) 
       print("Finish time in seconds \(time)") 

      } 
     } 
    } 
} 


class ProductRealm: Object { 
    public dynamic var id: String = "" 
    public dynamic var code: String = "" 
    public dynamic var detail: String = "" 
    public dynamic var onHand: Int = 0 
    public dynamic var price: Double = 0 
    public dynamic var isSerialized: Int = 0 
    public dynamic var isLotNumber: Int = 0 
    override static func primaryKey() -> String? { 
     return "id" 
    } 
} 

class GroupRealm: Object { 
    public dynamic var id = 1 
    public dynamic var name = "" 
    public dynamic var update = Date() 
    let products = List<ProductRealm>() 
    override static func primaryKey() -> String? { 
     return "id" 
    } 
}