2016-08-24 145 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