1. 程式人生 > >Python使用SQLite插入大量資料耗時問題

Python使用SQLite插入大量資料耗時問題

前言

使用Python爬蟲代理IP時,最先使用了sqlite作為儲存ip資料庫,sqlite簡單、靈活、輕量、開源,和檔案系統一樣。而當大量插入爬取的資料時,出現了嚴重的耗時,檢視一起資料後,發現:sqlite在每條insert都使用commit的時候,就相當於每次訪問時都要開啟一次檔案,從而引起了大量的I/O操作,耗時嚴重。
下面是每次插入後,提交事務處理,每次插入的時間,單位是秒。

    def insert(self, sql, data):
        '''
        insert data to the table
        :param sql:
        :param data:
        :return:
        '''
if sql is not None and sql != '': if data is not None: cu = self.getcursor() try: for d in data: cu.execute(sql, d) # 每次都執行事務提交 self.conn.commit() except sqlite3.Error as
why: print "insert data failed:", why.args[0] cu.close() else: print "sql is empty or None"
0.134000062943
0.132999897003
0.236999988556
0.134000062943
0.120000123978
0.155999898911
0.131999969482
0.142000198364
0.119999885559
0.176000118256
0.124000072479
0.115999937057
0.111000061035
0.119999885559

顯式使用事務的形式提交

在批量插入資料之後再進行事務提交,把大量操作的語句都儲存在記憶體中,當提交時才全部寫入資料庫,此時,資料庫檔案也就只用開啟一次,會顯著的提高效率。

    def insert(self, sql, data):
        '''
        insert data to the table
        :param sql:
        :param data:
        :return:
        '''
        if sql is not None and sql != '':
            if data is not None:
                cu = self.getcursor()
                try:
                    for d in data:
                        cu.execute(sql, d)
                except sqlite3.Error as why:
                    print "insert data failed:", why.args[0]
                # 批量插入之後再執行事務提交
                self.conn.commit()
                cu.close()
        else:
            print "sql is empty or None"

每次插入20行資料的時間如下,單位秒,很明顯的提高了效率

0.263999938965
0.117000102997
0.194999933243
0.263000011444
0.131000041962
0.15399980545
0.143000125885
0.12299990654
0.128000020981
0.121999979019
0.203999996185

寫同步和執行準備方法

寫同步

在SQLite中,資料庫配置的引數都由編譯指示(pragma)來實現的,而其中synchronous選項有三種可選狀態,分別是full、normal、off。官方文件

當synchronous設定為FULL (2), SQLite資料庫引擎在緊急時刻會暫停以確定資料已經寫入磁碟。這使系統崩潰或電源出問題時能確保資料庫在重起後不會損壞。FULL synchronous很安全但很慢。

當synchronous設定為NORMAL, SQLite資料庫引擎在大部分緊急時刻會暫停,但不像FULL模式下那麼頻繁。 NORMAL模式下有很小的機率(但不是不存在)發生電源故障導致資料庫損壞的情況。但實際上,在這種情況 下很可能你的硬碟已經不能使用,或者發生了其他的不可恢復的硬體錯誤。

設定為synchronous OFF (0)時,SQLite在傳遞資料給系統以後直接繼續而不暫停。若執行SQLite的應用程式崩潰, 資料不會損傷,但在系統崩潰或寫入資料時意外斷電的情況下資料庫可能會損壞。另一方面,在synchronous OFF時 一些操作可能會快50倍甚至更多。在SQLite 2中,預設值為NORMAL.而在3中修改為FULL。