關於批量插入:Python sqlite bult insert (mass-insertion) 【SQLObject vs sqlite3】

   個人遇到了一個需要互操作 Access 與 sqlite 的項目,其中涉及了諸多 join 和 relation。最重要的是數據的互相流動,這個項目使用了 pypyodbc 與 sqlobject,不免涉及了批量操作的問題。我將詳細記錄 sqlite 中的批量操作問題。


  • pypyodbc


   作爲數據源的 access 我將不會在本文中討論


  • SQLObject



   SQLObject 的操作速度一直是爲人所詬病的,在官方的 FAQ 中對於其不支持 Lazy Insert 的原因,其解釋道:

The reason for this limit is that each object needs a database ID,
不支持(lazy insert)的原因是每個對象都需要一個數據庫標識(db id)
and in many databases you cannot attain an ID until you create a row.
而在很多數據庫上只有插入一行後才能得到它(ID)


   它既然這麼說也無可厚非,純粹的架構問題。

   在隨後的一個問題:How to do mass-insertion? 中它又提出使用 SQLBuilder(官方:lower but much faster API) 來進行批量操作,例如用 sqlbuilder.Insert 和 sqlrepr() 生成 query 後,在 connection.query() 中執行,類似的 queryAll() 調用相同的數據庫方法,只是結果返回 fetchALL(),但是最終結果讓我不能仍受,插入100行幾乎就像無響應一樣,代碼如下:

from sqlobject.sqlbuilder import *
import sqlobject
sqlite_file = os.path.abspath('D:/db.sqlite')
conn = sqlobject.connectionForURI('sqlite:/'+sqlite_file)
_values = {}
for row in datas:
    # 在這裏我設置了 _values 的內容,like:
    # _values[column] = data
    insert = Insert('records', values=_values)
    a_query = conn.sqlrepr(insert)
    conn.query(a_query)


   當時無論怎麼看都是每次 query 都是 autocommit 的,果不其然非常之慢,執行了將近十秒,這開始讓我懷疑可能是我誤解的文檔的意圖,我在郵件列表上提問,目前還沒有收到答覆。


  • sqlite3


   

   隨後我嘗試了內置的 sqlite3,由於直接執行 sql 和手動提交,它的速度很少有人抱怨,我沒有花太多力氣就在官方文檔中找到了批量操作的方法:

   

c = conn.cursor()
purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
             ('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
             ('2006-04-06', 'SELL', 'IBM', 500, 53.00),
            ]
c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases)


   插入947行用了2秒,雖然需要手動編寫 insert SQL,但是這點代價可以接受

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章