Großes set (größer als Hauptspeicher)

07/03/2011 - 15:59 von Thomas Guettler | Report spam
Hallo,

die Daten einer Anwendung sind über die Jahre hinweg gewachsen,
so dass ein "Set" nicht mehr in den Hauptspeicher passt.

Der Algorithmus ist etwa so:

myset=set()
for :
myset.add(...)

for ...:
myset.remove(...)

for item in myset:
...

Ich möchte nicht all zuviel umstellen.

Gibt es da ein Modul, das mit rund 10 Millionen Eintràgen
umgehen kann?

Thomas

Thomas Guettler, http://www.thomas-guettler.de/
E-Mail: guettli (*) thomas-guettler + de
 

Lesen sie die antworten

#1 Peter Otten
07/03/2011 - 20:21 | Warnen spam
Thomas Guettler wrote:

Hallo,

die Daten einer Anwendung sind über die Jahre hinweg gewachsen,
so dass ein "Set" nicht mehr in den Hauptspeicher passt.

Der Algorithmus ist etwa so:

myset=set()
for :
myset.add(...)

for ...:
myset.remove(...)

for item in myset:
...

Ich möchte nicht all zuviel umstellen.

Gibt es da ein Modul, das mit rund 10 Millionen Eintràgen
umgehen kann?



Falls du nichts Fertiges findest, ist ein Datenbank-Wrapper relativ leicht
zu bauen:

from collections import MutableSet
import sqlite3

class DBSet(MutableSet):
def __init__(self, cursor, table, column):
self.cursor = cursor
self.table = table

self._contains = "select count(*) from %s where %s = ?" % (table,
column)
self._insert = "insert into %s (%s) values (?)" % (table, column)
self._len = "select count (*) from %s;" % table
self._iter = "select %s from %s order by %s" % (column, table,
column)
self._discard = "delete from %s where %s = ?" % (table, column)

def add(self, value):
try:
self.cursor.execute(self._insert, (value,))
except sqlite3.IntegrityError:
pass
def discard(self, value):
self.cursor.execute(self._discard, (value,))
def __contains__(self, value):
return next(self.cursor.execute(self._contains, (value,)))[0]
def __len__(self):
return next(self.cursor.execute(self._len))
def __iter__(self):
return (row[0] for row in self.cursor.execute(self._iter))

if __name__ == "__main__":
db = sqlite3.connect(":memory:")

cursor = db.cursor()
cursor.execute("create table example (x primary key);")

myset = DBSet(cursor, "example", "x")

for item in "alpha beta gamma delta ALPHA alpha".split():
myset.add(item)

for item in "ALPHA", "gamma", "gamma":
try:
myset.remove(item)
except KeyError as exc:
print exc

print "gamma" in myset, "delta" in myset

for item in myset:
print item

Das so zu modifizieren, dass Tupel von string/int/float akzeptiert werden,
sollte kein Problem sein. Ob die Performance ausreicht, musst du
ausprobieren.

Ähnliche fragen