2016-08-24 83 views
0

我是使用python和sqlite的新手。我正在尝试创建一个从表(Rawdata)中读取数据的脚本,然后执行一些计算,然后将其存储在一个新表中。我在计算一名球员在该日期之前在特定赛道位置赢得的比赛次数并计算出比例。共有15个轨道位置。总的来说,剧本非常缓慢。任何提高速度的建议。我已经使用了PRAGMA参数。在Sqlite中提高查询速度

以下是脚本。

for item in result: 
     l1 = str(item[0]) 
     l2 = item[1] 
     l3 = int(item[2]) 

     winpost = [] 
     key = l1.split("|") 
     dt = l2 

     ###Denominator-------------- 
     cursor.execute(
      "SELECT rowid FROM rawdata WHERE Track = ? AND Date< ? AND Distance = ? AND Surface =? AND OfficialFinish=1", 
      (key[2], dt, str(key[4]), str(key[5]),)) 
     result_den1 = cursor.fetchall() 
     cursor.execute(
      "SELECT rowid FROM rawdata WHERE Track = ? AND RaceSN<= ? AND Date= ? AND Distance = ? AND Surface =? AND OfficialFinish=1", 
      (key[2], int(key[3]), dt, str(key[4]), str(key[5]),)) 
     result_den2 = cursor.fetchall() 
     totalmat = len(result_den1) + len(result_den2) 

     if totalmat > 0: 

      for i in range(1, 16): 
       cursor.execute(
        "SELECT rowid FROM rawdata WHERE Track = ? AND Date< ? AND PolPosition = ? AND Distance = ? AND Surface =? AND OfficialFinish=1", 
        (key[2], dt, i, str(key[4]), str(key[5]),)) 
       result_num1 = cursor.fetchall() 
       cursor.execute(
        "SELECT rowid FROM rawdata WHERE Track = ? AND RaceSN<= ? AND Date= ? AND PolPosition = ? AND Distance = ? AND Surface =? AND OfficialFinish=1", 
        (key[2], int(key[3]), dt, i, str(key[4]), str(key[5]),)) 
       result_num2 = cursor.fetchall() 
       winpost.append(len(result_num1) + len(result_num2)) 

      winpost = [float(x)/totalmat for x in winpost] 
      rank = rankmin(winpost) 
      franks = list(rank) 
      franks.insert(0, int(key[3])) 
      franks.insert(0, dt) 
      franks.insert(0, l1) 
      table1.append(franks) 
      franks = [] 

    cursor.executemany("INSERT INTO posttable VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table1) 
+1

我认为,目标应该是让SQL机器做的工作,而不是Python的一个。尝试缩小SQL查询的数量。 – karlosss

回答

1

发送和检索SQL查询在时间上是“昂贵的”。加快速度的最简单方法是使用SQL函数来减少查询次数。

例如,前两个查询可以使用COUNT(),UNION和Aliases简化为单个调用。

SELECT COUNT(*) 
FROM 
(SELECT rowid FROM rawdata where ... 
    UNION 
    SELECT rowid FROM rawdata where ... 
) totalmatch 

在这种情况下,我们采取了两个原始查询(与你的条件地方的“...”)与UNION语句将它们组合起来,给那个工会别名‘totalmatch’,并计算所有在它的行。

第二组查询可以完成同样的事情。而不是在2个查询中循环16次(导致32个对SQL引擎的调用),您可以使用GROUP BY将其替换为一个查询。

SELECT PolPosition, COUNT(PolPosition) 
FROM 
(SELECT PolPosition FROM rawdata WHERE ... 
    UNION 
    SELECt PolPosition FROM rawdata WHERE ... 
) totalmatch 
GROUP BY PolPosition 

在这种情况下,我们采取了完全相同的查询和以前一样组通过它PolPosition,使用COUNT显示多少行各小组。

W3Schools的是这些功能是如何工作的一个很好的资源: http://www.w3schools.com/sql/default.asp

+0

UNION ALL比UNION更快。 –

+0

谢谢@TripleD。你的建议确实有帮助。我将查询数从34减少到只有1个。但是,我需要更多的帮助:鉴于我的数据库将有1M行,我相信sqlite不是一个好的解决方案。有没有其他解决方案。 –

+0

@Cl我不知道。谢谢。 – TripleD