2017-02-07 54 views
1

我有一個腳本,將數據庫中存儲的日期從Unix時間(紀元)轉換爲人類可讀的格式。有30,000條記錄。
要從數據庫中提取數據,將其轉換並打印到屏幕上的速度非常快。但是,爲了從數據庫中提取數據,將其轉換並執行「更新」語句來更新記錄,速度非常緩慢。
是否有無論如何優化下面的代碼,以加快我的30,000條記錄的這個過程?Python的SQLite - 慢UPDATE記錄

cur.execute('select Atime from Hash where Atime like (?) ', (test,)) 
    results = cur.fetchall() 
    for row in results: 
     convertedtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime((float(row[0])))) 
     print convertedtime 
     cur.execute('Update Hash set Atime = (?) where Atime = (?)', (convertedtime, row[0])) 
    con.commit() 

con.commit()是for循環外,使它不與每次迭代後提交記錄的問題。

+0

這是否做任何改變:https://sqlite.org/pragma.html#pragma_synchronous –

+0

多大分貝文件?你可能會嘗試將它全部導入熊貓,操作然後導出到sqlite。 – rshield

+0

可能是因爲該字段未被編入索引? – asiviero

回答

3

的主要性能問題是你拉出來的數據的SQLite,它加載到Python中,在Python轉換它,然後把它放回數據庫一個日期在時間。這永遠不會有效。

取而代之的是,use SQLite's own built in date and time functions。它看起來像是atime是Unix紀元時間。

update hash set atime = datetime(atime, 'unixepoch', 'localtime'); 

但你可能不想存儲日期在本地時區。時區變得複雜,並且夏令時有時間缺失和重疊時間......這隻會導致流淚。您絕對不希望在本地時區中存儲日期時間,而不指出該時區是什麼!

除非您有一個非常好的理由,否則將其存儲爲UTC。

update hash set atime = datetime(atime, 'unixepoch'); 

在一般情況下,如果你想要做的事情SQLite不支持的,創建用戶定義的函數和查詢使用它。這比使用內置的SQLite函數效率更低,但比選擇,轉換和更新效率更高。

它看起來像這樣。

def epoch_to_iso8601(epoch): 
    return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime((float(epoch)))) 

con.create_function("epoch_to_iso8601", 1, epoch_to_iso8601) 

然後,您可以在查詢中使用epoch_to_iso8601

update hash set atime = epoch_to_iso8601(atime); 

請注意,這與存儲過程不一樣。因爲沒有SQLite服務器,所有的代碼都在你的進程中運行,這個函數是每個進程的。

請參閱sqlite3.create_function


這裏真正的問題是你存儲日期時間爲字符串。這使他們變得緩慢和尷尬的工作。這意味着你必須選擇一種格式。這意味着您必須解析該格式才能對其執行任何操作。這意味着你不能使用內建的SQLite日期和時間函數(原樣稀疏)。

實際上你想要做的是將atime作爲Unix紀元時間,並根據每個查詢需要進行格式化。

select datetime(atime, 'unixepoch') from hash; 

幸運SQLite是非常loosey,鵝,其類型和將文本atime字段轉換爲數字給你,但它會導致性能和存儲處罰。


理想情況下,你會想改變atime使用datetime類型,但是這是在SQLite的困難。它不支持刪除或修改現有的列。相反,您必須轉儲表中的數據,重新創建表並導入數據。這應該是非常快的,只有30,000條記錄。

切換到CSV模式,將輸出發送到文件,然後選擇所有內容。

sqlite> .mode csv hash 
sqlite> .output hash.out 
sqlite> select * from hash; 

刪除現有表並重新創建它相同,但與atimedatetime

sqlite> drop table hash; 
sqlite> create table hash (atime datetime, and the other columns); 

導入轉儲。

sqlite> .import hash.out hash 
+1

感謝您的信息 - 查看並做一些測試並回報! –

+0

感謝您的幫助 - 我最終使用了以下命令:cur.execute(「UPDATE HASH SET Atime = datetime(Atime,(?))」,('unixepoch'))----- 工作就像一個魅力! –