2016-07-21 1 views
0

私はPython + MySQLdbでデータを抽出し、XMLファイルを生成し、それらを圧縮するためにcrontabジョブを設計しています。はい、アーカイブタスクは毎日正午に行われます。Python MySQLdbの応答時間は、奇妙なセットでは極端に異なります

私のコード:私のコードで

#!/usr/bin/env python 
#encoding: utf-8 
from dmconfig import DmConf 
#from dmdb import Dmdb 
import redis 
import MySQLdb 
import dawnutils 


import time 
from datetime import datetime, timedelta, date 

conf = DmConf().loadConf() 

db = MySQLdb.connect(host=conf["DbHost"],user=conf['DbAccount'],passwd=conf['DbPassword'],\ 
     db=conf['DbName'],charset=conf['DbCharset']) 
cache = redis.Redis(host=conf['RedisHost'], port=conf['RedisPort'], 
     db=conf['Redisdbid'], password=conf['RedisPassword']) 

#cursor = db.cursor() 

def try_reconnect(conn): 
    try: 
     conn.ping() 
    except: 
     conn = MySQLdb.connect(host=conf["DbHost"],user=conf['DbAccount'],passwd=conf['DbPassword'],\ 
      db=conf['DbName'],charset=conf['DbCharset']) 


def zip_task(device, start, stop): 
    #cursor = db.cursor() 
    format = "%Y%m%d%H%M%S" 
    begin = time.strftime("%Y-%m-%d %H:%M:%S",time.strptime(start,format)) 
    end = time.strftime("%Y-%m-%d %H:%M:%S",time.strptime(stop,format)) 
    print "%s (%s,%s)"%(device, begin, end) 
    sql = "SELECT * from `period` WHERE `snrCode` = \"%s\" AND `time` > \"%s\" AND `time` < \"%s\" ORDER BY `recId` DESC"%(device, begin, end) 
    print sql 
    cursor = db.cursor() 

    try_reconnect(db) 
    t1 = time.time() 
    try: 
     cursor.execute(sql) 
     results = cursor.fetchall() 
    except MySQLdb.Error,e: 
     print "Error %s"%(e) 

    print ("SQL takes %f seconds"%(time.time()-t1)) 

    print ("len of reconds, %d"%len(results)) 

    #for row in results: 
     #print row 


def dispatcher(devSet, start, stop): 
    print "size of set: %d"%len(devSet) 
    print devSet 
    for dev in devSet: 
     zip_task(dev, start, stop) 

def archive_task_queue(): 
    today = datetime.now() 
    oneday = timedelta(days=1) 
    yesterday = today - oneday 
    format = "%Y%m%d%H%M%S" 
    begin = time.strftime(format, yesterday.timetuple())[:8] + '120000' 
    end = time.strftime(format, today.timetuple())[:8] + '120000' 

    sql = "SELECT * from `logbook` WHERE `login` > \"%s\" AND `login` < \"%s\" AND `logout` > \"%s\" AND `logout` < \"%s\""%(begin, end, begin, end) 
    print sql 

    cursor = db.cursor() 
    reclist = [] 
    try: 
     cursor.execute(sql) 
     results = cursor.fetchall() 

     for row in results: 
      #print row 
      reclist.append(row[1]) 
    except MySQLdb.Error,e: 
     print "Error %s"%(e) 

    #reclist = [u'A2H300001'] 

    if len(reclist): 
     dispatcher(set(reclist), begin, end) 

    db.close() 

if __name__ == '__main__': 
    archive_task_queue() 

、私は、デバイスの活動のためのログブックを照会し、その日のために設定され、アクティブデバイスを取得します。また、各デバイスのクエリデータセットを1つずつ作成します。この問題は、第2段階のクエリに伴い発生します。実行後にコンソールを確認してください:

SELECT * from `logbook` WHERE `login` > "20160720120000" AND `login` < "20160721                  120000" AND `logout` > "20160720120000" AND `logout` < "20160721120000" 
size of set: 4 
set([u'B1H700001', u'B1H700002', u'A1E500018', u'A2H300001']) 
B1H700001 (2016-07-20 12:00:00,2016-07-21 12:00:00) 
SELECT * from `period` WHERE `snrCode` = "B1H700001" AND `time` > "2016-07-20 12                  :00:00" AND `time` < "2016-07-21 12:00:00" ORDER BY `recId` DESC 
SQL takes 0.018232 seconds 
len of reconds, 597 
B1H700002 (2016-07-20 12:00:00,2016-07-21 12:00:00) 
SELECT * from `period` WHERE `snrCode` = "B1H700002" AND `time` > "2016-07-20 12                  :00:00" AND `time` < "2016-07-21 12:00:00" ORDER BY `recId` DESC 
SQL takes 0.974020 seconds 
len of reconds, 4642 
A1E500018 (2016-07-20 12:00:00,2016-07-21 12:00:00) 
SELECT * from `period` WHERE `snrCode` = "A1E500018" AND `time` > "2016-07-20 12                  :00:00" AND `time` < "2016-07-21 12:00:00" ORDER BY `recId` DESC 
SQL takes 0.342373 seconds 
len of reconds, 0 
A2H300001 (2016-07-20 12:00:00,2016-07-21 12:00:00) 
SELECT * from `period` WHERE `snrCode` = "A2H300001" AND `time` > "2016-07-20 12                  :00:00" AND `time` < "2016-07-21 12:00:00" ORDER BY `recId` DESC 

SQL takes 68.173677 seconds 
len of reconds, 5794 

クエリ時間が掛かっています。 B1H700002 4642データポイントの場合は0.9秒かかりますが、A2H300001 5764データポイントの場合は68秒かかります。

次に、私の前のコードで見つけることができる特定のデバイスIDだけを問い合わせるように問題を絞り込みます。結果は同じです。そのクエリには65秒かかります。

ヒント?

+0

'show create table logbook'と' select count(*)from logbook' – Drew

答えて

0

このSQLクエリでは、より多くのラボを実行しました。最後に、MySQLdbのメモリ使用量に関連していることがわかりました。合計データセットは5794行しかないかもしれませんが、LIMIT 5000を追加するとクエリは0.3秒しかかかりません。それ以外の場合は60+秒かかります。

回避策として、私はLIMITといくつかのページ分割メトトを使って、各クエリの限られた行をクエリし、前のクエリに追加します。合計時間は1秒以内に短縮されます。

関連する問題