为什么查询时间会减少,但实现索引时整体代码时间会增加?

时间:2015-03-08 16:15:33

标签: python sql sqlite indexing

我使用unixtime和userid遍历大量消息,我想在每个用户的24小时时间内找到消息数。我在codereview上发布了我的代码以获得一些帮助。从那里我优化了

cur.execute('SELECT unixtime FROM MessageType1 WHERE userID ='+str(userID[index])+' ORDER BY unixtime asc')

查询,因为我发现它损害了我的代码总运行时间7.2s的6.7s。我通过使用CREATE INDEX unixtime_times ON MessageType1 (unixtime asc)在unixtime列上创建索引来优化它。现在该查询需要0.00117s而不是6.7s,但运行我的代码所需的总时间从7.2s增加到15.8s。除了索引之外,一切都没有变化。经过进一步检查,似乎messages = cur.fetchall()在实施索引后需要15.3秒。有谁知道为什么?提前谢谢!

con = lite.connect(databasepath)
    userID = []
    messages = []
    messageFrequency = []
    with con:
        cur = con.cursor()
        #Get all UserID
        cur.execute('SELECT DISTINCT userid FROM MessageType1')
        userID = cur.fetchall()
        userID = {index:x[0] for index,x in enumerate(userID)}
        #For each UserID
        for index in range(len(userID)):
            messageFrequency.append(0)
            #Get all MSG with UserID = UserID sorted by UNIXTIME
            cur.execute('SELECT unixtime FROM MessageType1 WHERE userID ='+str(userID[index])+' ORDER BY unixtime asc')
            messages = cur.fetchall()
            messages = {index:x[0] for index,x in enumerate(messages)}
            #Loop through every MSG
            for messageIndex in range(len(messages)):
                frequency = 0
                message = messages[messageIndex]
                for nextMessageIndex in range(messageIndex+1, len(messages)):
                #Loop through every message that is within 24 hours
                    nextmessage = messages[nextMessageIndex]
                    if  nextmessage < message+(24*60*60):
                    #Count the number of occurences
                        frequency += 1
                    else:
                        break
                #Add best benchmark for every message to a list that should be plotted.
                if messageFrequency[-1]<frequency:
                    messageFrequency[-1] = frequency

1 个答案:

答案 0 :(得分:2)

此查询的最佳索引:

SELECT unixtime
FROM MessageType1
WHERE userID ='+str(userID[index])+'
ORDER BY unixtime asc

MessageType1(UserId, unixtime)

仅使用unixtime索引,数据库基本上有两个可能的执行计划:

  1. 它可以忽略索引,“按顺序”读取行,过滤它们,然后进行排序。
  2. 它可以按排序顺序从索引返回行,然后在输出中过滤。
  3. 我的猜测是,它会根据您的时间选择第二种方法。处理的“获取”组件结束了查询的执行,因此非常快。然后它必须读取整个表格以获得您想要的结果。

    由于地点问题,此方法可能需要更长时间才能按顺序读取数据。没有索引,它将读取第一页和第一页上的所有记录。使用索引,每条记录都在随机页面上 - 没有位置。当表大于可用于页面缓存的内存时,这可能会特别成问题,并且最终会出现称为“颠簸”的情况。