2017-09-16 7 views
1

既存のSQLiteデータベースに接続し、キー列の値とデータフレームの値を比較する必要があります。データベースとデータフレーム間のすべてのキー一致に対して、その行の特定の列の値を更新します。キーがデータフレームに存在し、データベースに存在しない場合は、それぞれの行をデータベースに追加します。ターゲットは比較的大きなデータセットであるため、メモリの使用とパフォーマンスが懸念されます(20〜60 GBのdb、@〜20列、および何百万行もの可能性があります)。条件を使ってSQLite DBを更新して列の値を変更するか、新しい行を追加する

以前はデータベースをデータフレームに読み込み、古いデータフレームと新しいデータフレームをメモリにマージしようとしましたが、高価であることが判明しました(多くの場合、5ギガバイトのデータセットがメモリに20ギガヘルツになります)。

私はここのロジックで迷子だ、これは私が行ってきた最も遠いです:新しいデータで

Key  First_Seen Last_Seen Data1 Data2 
Bigfoot 2015  2015  Blah Blah 
Loch_Ness 2016  2016  Blah Blah 
UFO  2016  2004  Blah Blah  

データフレームを

データベース:

def update_column(tablename, key_value): 
    c.execute('SELECT key FROM {}'.format(tablename)) 
    for row in c.fetchall(): 
     # populating this key value per row is challenging for me 
     if row == key_value: 
      c.execute('UPDATE {} SET last_seen = {} WHERE UUID = {}}'.format(tablename, hunt_date, key_value)) 
     else: 
      df.to_sql(table_name, if_exists='append') 

for index, row in reader.iterrows(): 
    key_value = row['key'] 
    update_column(tablename, key_value) 

例データセット:

Key  First_Seen Last_Seen Data Data 
UFO  2017  2017  Blah Blah 
Tupac  2017  2017  Blah Blah 

データベースでの出力を希望する:

Key  First_Seen Last_Seen Data Data 
Bigfoot 2015  2015  Blah Blah 
Loch_Ness 2016  2016  Blah Blah 
UFO  2016  2017  Blah Blah 
Tupac  2017  2017  Blah Blah 

答えて

1

示唆したように、SQLiteの中に一時テーブルを考慮し、UPDATEINSERT INTOクエリを実行します。何百万行も繰り返す必要はありません。

SQLiteはUPDATE...JOINをサポートしていないので、IN節のようなサブクエリが必要です。新しいキー行しか追加しないので、毎回追加クエリを実行することに問題はありません。

df.to_sql('pandastable', conn, if_exists='replace') 

c.execute("UPDATE finaltable f " + \ 
      "SET f.last_seen = p.last_seen " + \ 
      "WHERE f.[key] IN (SELECT p.[key] FROM pandastable p);") 
conn.commit() 

c.execute("INSERT INTO finaltable ([key], first_seen, last_seen, blah, blah, blah) " + \ 
      "SELECT [key], first_seen, last_seen, blah, blah, blah " + \ 
      "FROM pandastable p " + \ 
      "WHERE NOT EXISTS " + \ 
      " (SELECT 1 FROM finaltable sub " + \ 
      " WHERE sub.[key] = p.[key]);") 
conn.commit() 

、代わりに生の接続のSQLAlchemyでパンダを接続する場合は、代わりにカーソルコールの取引でアクションクエリを実行している考慮:

import sqlalchemy 

... 
engine = sqlalchemy.create_engine("sqlite:sqlite:////path/to/database.db") 

df.to_sql(name='pandastable', con=engine, if_exists='replace') 

# SQL ACTIONS USING TRANSACTIONS 
with engine.begin() as conn:  
    conn.execute("UPDATE finaltable f " + \ 
       "SET f.last_seen = p.last_seen " + \ 
       "WHERE f.[key] IN (SELECT p.[key] FROM pandastable p);") 

with engine.begin() as conn:  
    conn.execute("INSERT INTO finaltable ([key], first_seen, last_seen, blah, blah, blah) " + \ 
       "SELECT [key], first_seen, last_seen, blah, blah, blah " + \ 
       "FROM pandastable p " + \ 
       "WHERE NOT EXISTS " + \ 
       " (SELECT 1 FROM finaltable sub " + \ 
       " WHERE sub.[key] = p.[key]);") 

engine.dispose() 
1

私はSQLite側でこのような更新を行います。

第1の一時的SQLiteのテーブルとしてあなたのDFを保存:tmp

df.to_sql('tmp', conn, if_exists='replace') 

sql = """ 
UPDATE table_name set last_seen = (SELECT t.last_seen 
            FROM tmp t 
            WHERE t.Key = table_name.key) 
WHERE EXISTS(
    SELECT * 
    FROM tmp 
    WHERE tmp.key = table_name.key 
) 
""" 

c.execute(sql) 
関連する問題