tool_id、時間、およびメッセージを含むタプルのリストがあります。このリストから、メッセージがいくつかの文字列と一致するすべての要素と、時間がそのツールの一致するメッセージの差分内にある他のすべての要素を選択したいと思います。
これが私が現在これを行っている方法です:
# record time for each message matching the specified message for each tool
messageTimes = {}
for row in cdata: # tool, time, message
if self.message in row[2]:
messageTimes[row[0], row[1]] = 1
# now pull out each message that is within the time diff for each matched message
# as well as the matched messages themselves
def determine(tup):
if self.message in tup[2]: return True # matched message
for (tool, date_time) in messageTimes:
if tool == tup[0]:
if abs(date_time-tup[1]) <= tdiff:
return True
return False
cdata[:] = [tup for tup in cdata if determine(tup)]
このコードは機能しますが、実行に時間がかかりすぎます。たとえば、cdataに600,000個の要素がある場合(これは私のアプリでは一般的です)、実行には2時間かかります。
このデータはデータベースからのものです。元々、SQLを使用して必要なデータだけを取得していましたが、それも時間がかかりすぎました。必要なメッセージだけを選択し、次に別のクエリを実行するメッセージごとに、それぞれの時間差内でデータを取得していました。その結果、何万ものクエリが発生しました。そこで、すべての潜在的な一致を一度にプルしてから、Pythonで処理するように変更しました。これは、より高速になると考えています。多分私は間違っていた。
誰かがこれをスピードアップするためのいくつかの提案を私に与えることができますか?
提案されたようにSQLで何をしたかを示すために投稿を更新します。
SQLで行ったことは非常に簡単でした。最初のクエリは次のようなものでした。
SELECT tool, date_time, message
FROM event_log
WHERE message LIKE '%foo%'
AND other selection criteria
これは十分に高速でしたが、2万または3万行を返す可能性があります。次に、結果セットをループし、各行に対して次のようなクエリを実行しました(dtとtは、上記の行からのdate_timeとツールです)。
SELECT date_time, message
FROM event_log
WHERE tool = t
AND ABS(TIMESTAMPDIFF(SECOND, date_time, dt)) <= timediff
それは約1時間かかりました。
また、内側のクエリが最初のクエリから行を選択し、外側のクエリが時間差分行を選択する1つのネストされたクエリで実行しようとしました。それにはさらに時間がかかりました。
だから今私はメッセージLIKE'%foo%'句なしで選択していて、600,000行を取り戻し、Pythonから必要な行を引き出そうとしています。