热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

插入到sqlite数据库需要花费太多时间——iOS-insertingintosqlitedatabasetakingtoomuchtime-iOS

Ihave6000recordsofPhoneBookIminsertingintosqliteitstaking45seconds,thatishugetime.

I have 6000 records of PhoneBook I'm inserting into sqlite its taking 45 seconds, that is huge time.

我把6000个电话簿记录插入到sqlite中只要45秒,时间太长了。

for each record I want only few properties like name, email, id, modified date. So atleast one for loop i need because of that its taking 45 seconds. How can i reduce?

对于每条记录,我只需要一些属性,比如名称、电子邮件、id、修改日期。所以我至少需要一个for循环因为它需要45秒。我怎么能减少?

Here is the updated code (This code is running in dispatch_async)

这是更新后的代码(此代码在dispatch_async中运行)

I also checked similar problem How to insert 40000 records fast into an sqlite database in an iPad solution says I've to use BEGIN & END transaction that i used already but still facing the same.

我还检查了类似的问题:如何在iPad解决方案中快速将40000条记录插入到一个sqlite数据库中。

UPDATE - As per suggested solutions i've updated my code but still its taking 45 seconds. Please help me.

更新——根据建议的解决方案,我更新了我的代码,但仍然需要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 

Here is insertIntoContact func.

这是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)
}

For more details

为更多的细节

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
}

2 个解决方案

#1


4  

You need to use BEGIN TRANSACTION before starting to iterate over 6000 records and END TRANSACTION after all entries addition has been issued - this way you will lower I/O load and make things happened faster.

您需要在开始迭代超过6000条记录和所有添加条目之后的结束事务之前使用BEGIN事务—这样您将降低I/O负载并使事情发生得更快。

#2


3  

1st Problem (NSDateFormatter allocations):

You are creating a new instance of NSDateFormatter on every loop. That means you created it 6000 times.....and it's really expensive to create an instance. So move that out of the loop. (see code sample below)

您正在每个循环上创建一个新的NSDateFormatter实例。这意味着你创造了6000倍的数据。创建实例非常昂贵。把它移出循环。(参见下面的代码示例)

2nd Problem (Use transactions):

Then you need to begin the transaction at this point as the previous answer suggested. After you have looped through the contacts you end the transaction as suggested from previous answer.

然后您需要按照前面的答案开始事务。在您循环通过联系人之后,您结束了交易建议从先前的回答。

Some pseudo code that needs better error checking:

I've put all sqlite related functions in the loop so it's easier to see what exactly is going on. But you really need to find out what is taking time, because you should have seen an increase in performance using transactions.

我已经将所有与sqlite相关的函数放在循环中,这样就更容易看到实际情况。但是,您确实需要找出什么需要花费时间,因为您应该已经看到了使用事务的性能提高。

struct Contact
{
    let name: String
    let number: String
    let email: String
    let modificationDate: String
    let id: Int32
}

Method to get contact from ABRecordRef

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 

Update the loop to something similar to yours

// 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)

推荐阅读
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
  • ECMA262规定typeof操作符的返回值和instanceof的使用方法
    本文介绍了ECMA262规定的typeof操作符对不同类型的变量的返回值,以及instanceof操作符的使用方法。同时还提到了在不同浏览器中对正则表达式应用typeof操作符的返回值的差异。 ... [详细]
author-avatar
GXTV杨波
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有