欢迎光临!
若无相欠,怎会相见

PyQt5 写入大量数据到 SQLite 数据库

序言

继续搞个人项目, 我需要把大量的基金数据写入到 SQLite 数据库中, 但是经过实践, 发现有个致命问题, 写入太慢了, 直接把 GUI 拖垮, 无响应。

正文

我曾经使用的方法一:

def saveAllFunds2DB(db: QSqlDatabase, already=False) -> bool:
    with open(ALL_FUNDS, 'r') as f:
        a = f.readline()
        all = a[a.find('=') + 2:a.rfind(';')]
        all_list = json.loads(all)
        query = QSqlQuery()
        for i in all_list:
        # 1384.7624049186707
            sql = f'''INSERT INTO FundAll (fund_code, fund_short_name, fund_name, fund_type, fund_long_name)
                      VALUES {tuple(i)}'''
            query.exec(sql)

最笨的方法, 一条数据插入一次数据库, 结果用时 1384 秒才把 15626 支基金的基础信息填写到 SQLite 中, 当然我的硬盘是机械硬盘, 要是 SSD 应该会加快一些, 但是还是会把 GUI 给卡死。 但是我的数据其实并不复杂, 如图:

然后尝试第二种方法:

def saveAllFunds2DB(db: QSqlDatabase, already=False) -> bool:
    with open(ALL_FUNDS, 'r') as f:
        a = f.readline()
        all = a[a.find('=') + 2:a.rfind(';')]
        all_list = json.loads(all)
        query = QSqlQuery()
        query.prepare('''INSERT INTO FundAlls (fund_code, fund_short_name, fund_name, fund_type, fund_long_name)
                      VALUES (?, ?, ?, ?, ?)''')
        fcode, fsname, fname, ftype, flname = [], [], [], [], []
        for i in all_list:
            fcode.append(i[0])
            fsname.append(i[1])
            fname.append(i[2])
            ftype.append(i[3])
            flname.append(i[4])
        query.addBindValue(fcode)
        query.addBindValue(fsname)
        query.addBindValue(fname)
        query.addBindValue(ftype)
        query.addBindValue(flname)
        return query.execBatch()

我在网络上搜索的时候是批量插入, 但是在实际运行中, 感觉和第一种方法一样, 而且由于我用电脑在做其他事, 导致运行时间达到 1454 秒才把这 15626 支基金基础信息添加到数据库中。

算了, 就当是实操记录了, 给自己一个教训, 实操哪种性能更好, 哈哈~

我尝试的第三种方法:将所有的 value 值添加到 SQL 语句中, 然后执行

def saveAllFunds2DB(db: QSqlDatabase, already=False) -> bool:
    with open(ALL_FUNDS, 'r') as f:
        a = f.readline()
        all = a[a.find('=') + 2:a.rfind(';')]
        all_list = json.loads(all)
        query = QSqlQuery()
        string = ''
        # 构造 Value 值字符串
        for i in all_list:
            string += str(tuple(i))
            string += ','
        return query.exec((f'''INSERT INTO FundAlls (fund_code, fund_short_name, fund_name, fund_type, fund_long_name)
                       VALUES %s''' % string[:-1]))

这种方法很快,用了 0.64 秒将 15626 条数据添加到数据库中, 但是有个缺点是需要构造 value 值字符串, 有点儿伤脑筋。

我尝试的第四中方法:使用事务

def saveAllFunds2DB(db: QSqlDatabase, already=False) -> bool:
    with open(ALL_FUNDS, 'r') as f:
        a = f.readline()
        all = a[a.find('=') + 2:a.rfind(';')]
        all_list = json.loads(all)
        db.transaction()
        query = QSqlQuery()
        # 0.6606760025024414
        for i in all_list:
            query.exec(f'''INSERT INTO FundAlls (fund_code, fund_short_name, fund_name, fund_type, fund_long_name)
                      VALUES {tuple(i)}''')
        return db.commit()

这种方法很强, 就 0.66 秒就把 15626 支基金的基础信息添加到数据库中了。

那到此, 我找到自己想要的方法了, 使用事务即快速, 有不用伤脑筋构造 value 值的字符串, 挨个迭代也没关系。

结语

以上执行的时间, 包含了整个函数, 并不是 SQL 的执行时间, 不过 SQL 执行时间应该占了 99.9% 的时间。 因为那个文件并不大。

之前拿数据的时候, 我用的是最笨的方法, 拿 1.35 GB 的数据, 用了 3 天 3 夜, 是在云上跑的, 硬盘还是 SSD 的, 如果是我本地跑, 估计能把我的电脑的机械硬盘写挂掉。 现在又学到一个知识, 以后写数据用事务, 即快捷, 还不用构造 value 字符串。

如有错误, 敬请指出, 感谢指正!     — 2022-05-19 21:39:36

 

赞(0) 打赏
转载请注明:飘零博客 » PyQt5 写入大量数据到 SQLite 数据库
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

欢迎光临