如何让我的代码更高效?

Lar*_*ell 3 python

我有一个包含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)] 
Run Code Online (Sandbox Code Playgroud)

这段代码有效,但运行时间太长 - 例如,当cdata有600,000个元素(这是我的应用程序的典型代码)时,运行需要2个小时.

这些数据来自数据库.最初我只使用SQL获取了我想要的数据,但这也花了太长时间.我只选择了我想要的消息,然后为每个进行另一个查询的消息选择每个消息的时间差异.这导致了成千上万的查询.所以我改变它以立即拉出所有潜在的匹配,然后在python中处理它,认为这会更快.也许我错了.

有人能给我一些关于加快这个速度的建议吗?

更新我的帖子以显示我在SQL中所做的事情.

我在SQL中所做的非常简单.第一个查询是这样的:

SELECT tool, date_time, message 
FROM event_log
WHERE message LIKE '%foo%'
AND other selection criteria
Run Code Online (Sandbox Code Playgroud)

这足够快,但可能会返回20或3万行.然后我循环遍历结果集,并为每一行运行这样的查询(其中dt和t是来自上面选择的行中的date_time和工具):

SELECT date_time, message
FROM event_log
WHERE tool = t 
AND ABS(TIMESTAMPDIFF(SECOND, date_time, dt)) <= timediff
Run Code Online (Sandbox Code Playgroud)

那花了大约一个小时.

我还尝试在一个嵌套查询中进行,其中内部查询从我的第一个查询中选择行,外部查询选择时间差异行.这花了更长的时间.

所以现在我选择没有消息LIKE'%foo%'子句,我回来600,000行,并试图从python中拉出我想要的行.

aba*_*ert 6

优化SQL的方法是在一个查询中完成所有操作,而不是迭代超过20K行并为每个查询执行另一个查询.

通常这意味着您需要添加JOIN,或偶尔添加子查询.是的,只要重命名一个或两个副本,就可以将表连接到自身.所以,像这样:

SELECT el2.date_time, el2.message 
FROM event_log as el1 JOIN event_log as el2
WHERE el1.message LIKE '%foo%'
AND other selection criteria
AND el2.tool = el1.tool
AND ABS(TIMESTAMPDIFF(SECOND, el2.datetime, el1.datetime)) <= el1.timediff
Run Code Online (Sandbox Code Playgroud)

现在,这可能不会快速开箱即用,因此有两个步骤可以改进它.

首先,查找显然需要编制索引的任何列.显然tool,datetime需要简单的指数.message可以从一个简单的索引中受益,或者,如果你的数据库有更高级的东西,可能更高级,但鉴于初始查询足够快,你可能不需要担心它.

偶尔,这就足够了.但通常情况下,你无法正确猜测一切.并且可能还需要重新排列查询的顺序等等.因此,您将需要EXPLAIN查询,并查看数据库引擎正在执行的步骤,并查看它在何时执行缓慢的迭代查找可以进行快速索引查找,也可以在小集合之前迭代大集合.