我有6000条电话簿记录我插入sqlite 它需要45秒,这是一个巨大的时间。
对于每条记录我只想要几个属性,如姓名,电子邮件,身份证,修改日期。所以至少需要一个for循环,因为它需要45秒。 我该如何减少?
这是更新的代码(此代码在dispatch_async中运行)
我还检查了类似的问题How to insert 40000 records fast into an sqlite database in an iPad解决方案说我已经使用了BEGIN&我已经使用但仍然面临同样的END交易。
更新 - 根据建议的解决方案,我已经更新了我的代码,但仍需要45秒。请帮帮我。
sqlite3_exec(db.insertPerson, "BEGIN TRANSACTION", nil, nil, nil)
for record:ABRecordRef in contactList
{
contactNumber = ""
email = ""
fullName = ""
if (ABRecordCopyValue(record,kABPersonPhoneProperty) != nil) && (ABRecordCopyValue(record,kABPersonFirstNameProperty) != nil)
{
firstName = (ABRecordCopyValue(record, kABPersonFirstNameProperty)?.takeRetainedValue() as? String)!
let numbers:ABMultiValue = ABRecordCopyValue(record, kABPersonPhoneProperty).takeRetainedValue()
if (ABMultiValueGetCount(numbers) > 0)
{
contactNumber = (ABMultiValueCopyValueAtIndex(numbers,0)?.takeRetainedValue() as? String)!
}
let modificationNSDate = (ABRecordCopyValue(record, kABPersonModificationDateProperty)?.takeRetainedValue())! as! NSDate
modificationDate = dateFormatter.stringFromDate(modificationNSDate)
recordId = ABRecordGetRecordID(record)
if (ABRecordCopyValue(record,
kABPersonLastNameProperty) != nil)
{
lastName = (ABRecordCopyValue(record,
kABPersonLastNameProperty).takeRetainedValue()as? String)!
}
let emails: ABMultiValueRef = ABRecordCopyValue(record, kABPersonEmailProperty).takeRetainedValue()
for (var i = 0; i < ABMultiValueGetCount(emails); i++)
{
email = ABMultiValueCopyValueAtIndex(emails, i).takeRetainedValue() as! String
}
}
fullName = "\(firstName) \(lastName)";
lastName = "";
db.insertIntoContact(contactName: fullName, contactNumber: contactNumber, contactEmail: email, recordid : recordId, modifieddate: modificationDate)
}
sqlite3_exec(db.insertPerson, "END TRANSACTION", nil, nil, nil)
这是insertIntoContact func 。
func insertIntoContact(contactName contactName : String!, contactNumber : String!, contactEmail : String!, recordid:Int32!, modifieddate:String! ) -> Bool
{
sqlite3_bind_text(insertPerson, 1, (contactName as NSString).UTF8String, -1, nil)
sqlite3_bind_text(insertPerson, 2, (contactNumber as NSString).UTF8String, -1, nil)
sqlite3_bind_text(insertPerson, 3, (contactEmail as NSString).UTF8String, -1, nil)
sqlite3_bind_int(insertPerson, 4, Int32(recordid))
sqlite3_bind_text(insertPerson, 5, (modifieddate as NSString).UTF8String, -1, nil)
return executeUpdate(sqlStatement: insertPerson)
}
了解更多详情
func executeUpdate(sqlStatement statement:COpaquePointer) -> Bool
{
let resultCode = executeStatement(sqlStatement: statement, success:Int(SQLITE_DONE))
sqlite3_reset(statement)
return resultCode
}
func executeStatement(sqlStatement statement:COpaquePointer,success successConstant:Int) -> Bool
{
let success = Int(sqlite3_step(statement))
if success != successConstant
{
print("Statement \(successConstant) failed with error \(success)")
return false
}
return true
}
答案 0 :(得分:4)
在开始迭代超过6000条记录之前,您需要使用BEGIN TRANSACTION
,并且在发出所有条目添加后END TRANSACTION
- 这样您将降低I / O负载并使事情更快地发生。
答案 1 :(得分:3)
您正在每个循环上创建一个新的NSDateFormatter实例。这意味着你创建了6000次.....并且创建一个实例真的很贵。所以把它移出循环。 (见下面的代码示例)
然后,您需要在此时开始事务,如前面的答案所示。在您完成联系后,您可以按照上一个答案的建议结束交易。
我已将所有与sqlite相关的函数放在循环中,以便更容易看到究竟发生了什么。但是你真的需要找出花时间的东西,因为你应该看到使用交易增加了性能。
struct Contact
{
let name: String
let number: String
let email: String
let modificationDate: String
let id: Int32
}
func contactFromABRecordRef(record: ABRecordRef, dateFormatter: NSDateFormatter) -> Contact?
{
var email = ""
var contactNumber = ""
var firstName = ""
var lastName = ""
var modificationDate = ""
var id: Int32 = -1
if (ABRecordCopyValue(record, kABPersonPhoneProperty) != nil)
{
let modificationNSDate = (ABRecordCopyValue(record, kABPersonModificationDateProperty)?.takeRetainedValue())! as! NSDate
modificationDate = dateFormatter.stringFromDate(modificationNSDate)
id = ABRecordGetRecordID(record)
let numbers: ABMultiValue = ABRecordCopyValue(record, kABPersonPhoneProperty).takeRetainedValue()
if (ABMultiValueGetCount(numbers) > 0)
{
contactNumber = (ABMultiValueCopyValueAtIndex(numbers,0)?.takeRetainedValue() as? String)!
}
if (ABRecordCopyValue(record, kABPersonFirstNameProperty) != nil)
{
firstName = (ABRecordCopyValue(record, kABPersonFirstNameProperty)?.takeRetainedValue() as? String)!
}
if (ABRecordCopyValue(record, kABPersonLastNameProperty) != nil)
{
lastName = (ABRecordCopyValue(record, kABPersonLastNameProperty).takeRetainedValue()as? String)!
}
let emails: ABMultiValueRef = ABRecordCopyValue(record, kABPersonEmailProperty).takeRetainedValue()
for (var i = 0; i < ABMultiValueGetCount(emails); i++)
{
email = ABMultiValueCopyValueAtIndex(emails, i).takeRetainedValue() as! String
}
return Contact(name: "\(firstName) \(lastName)", number: contactNumber, email: email, modificationDate: modificationDate, id: id)
}
return nil
}
// Load your contact list from here
let contactList: [ABRecordRef] = []
let dateFormatter: NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
sqlite3_exec(db, "BEGIN TRANSACTION", nil, nil, nil)
var statement: COpaquePointer = nil
if sqlite3_prepare_v2(db, "insert into contacts values (?1, ?2, ?3, ?4, ?5)", -1, &statement, nil) != SQLITE_OK
{
let errmsg = String.fromCString(sqlite3_errmsg(db))
// Handle the error message here!!!!
print("Error when preparing statement: ", errmsg)
}
for record: ABRecordRef in contactList
{
if let contact = contactFromABRecordRef(record, dateFormatter: dateFormatter)
{
sqlite3_bind_text(statement, 1, (contact.name as NSString).UTF8String, -1, nil)
sqlite3_bind_text(statement, 2, (contact.number as NSString).UTF8String, -1, nil)
sqlite3_bind_text(statement, 3, (contact.email as NSString).UTF8String, -1, nil)
sqlite3_bind_int(statement, 4, Int32(contact.id))
sqlite3_bind_text(statement, 5, (contact.modificationDate as NSString).UTF8String, -1, nil)
if sqlite3_step(statement) != SQLITE_DONE
{
let errmsg = String.fromCString(sqlite3_errmsg(db))
// Handle the error message here!!!!
print("Error when stepping through statement: ", errmsg)
}
sqlite3_reset(statement)
}
}
if sqlite3_exec(db, "COMMIT TRANSACTION", nil, nil, nil) != SQLITE_OK
{
let errmsg = String.fromCString(sqlite3_errmsg(db))
print("Error when commiting transaction: ", errmsg)
}
sqlite3_finalize(statement)