博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Python实战(6)单线程和多线程导入mysql数据对比测试

Posted on 2018-01-10 22:50  moss_tan_jun  阅读(500)  评论(0编辑  收藏  举报

单线程脚本

 导入文件的行数

# wc -l /data/logs/testlog/20120219/testlog1/*
 1510503 total

  1. # -*- coding: utf-8 -*-    
  2. #!/usr/bin/env python 
  3. #create database pythondata 
  4. #create table log (logline varchar(500)); 
  5. #grant all on pythondata.* to 'pyuser'@'localhost' identified by "pypasswd"; 
  6. import MySQLdb 
  7. import os 
  8. import time 
  9.  
  10. def writeLinestoDb(sql,content): 
  11.         conn=MySQLdb.connect(host="localhost",user="pyuser",passwd="pypasswd",db="pythondata") 
  12.         cur =conn.cursor() 
  13.         cur.executemany(sql,content) 
  14.         cur.close() 
  15.         conn.commit() 
  16.         conn.close() 
  17.  
  18. def readLinestoList(path): 
  19.         alllines=[] 
  20.         for file in os.listdir(path): 
  21.                 files=os.path.join(path,file) 
  22.                 for line in open(files): 
  23.                          alllines.append(line) 
  24.         return alllines 
  25.  
  26. def main(): 
  27.         insertsql ="INSERT INTO log(logline) VALUES(%s)" 
  28.         alllines=readLinestoList('/data/logs/testlog/20120219/testlog1')
  29.         for line in alllines: 
  30.                 content=line.strip() 
  31.                 print content 
  32.                 writeLinestoDb(insertsql,content) 
  33.                 time.sleep(10) 
  34.  
  35. if __name__=="__main__": 
  36.         print('starting at:',time.ctime()) 
  37.         main() 
  38.         print('ending at:',time.ctime()) 


 

('starting at:', 'Tue Mar 27 11:09:20 2012')
('ending at:', 'Tue Mar 27 11:13:20 2012')
耗时4分钟
mysql> select count(*) from log ;
+----------+
| count(*) |
+----------+
|  1510551 |
+----------+

多线程脚本

 

  1. # -*- coding: utf-8 -*-    
  2. #!/usr/bin/env python 
  3. import MySQLdb 
  4. import os 
  5. from time import ctime 
  6. from threading import Thread 
  7. from Queue import Queue 
  8. in_num_thread=10 
  9. out_num_thread=10 
  10. in_queue=Queue() 
  11. out_queue=Queue() 
  12.  
  13. def listDir(path): 
  14.         for filename in os.listdir(path): 
  15.                 in_queue.put(os.path.join(path,filename)) 
  16. def readFile(iq,in_queue): 
  17.         filelines=[] 
  18.         while True: 
  19.             file=in_queue.get() 
  20.             for line in open(file): 
  21.                 filelines.append(line) 
  22.             out_queue.put(filelines) 
  23.             in_queue.task_done()         
  24. def writeLinestoDb(oq,out_queue): 
  25.         sql=insertsql ="INSERT INTO log(logline) VALUES(%s)" 
  26.         while True: 
  27.             content=out_queue.get() 
  28.             conn=MySQLdb.connect(host="localhost",user="pyuser",passwd="pypasswd",db="pythondata") 
  29.             cur =conn.cursor() 
  30.             cur.executemany(sql,content) 
  31.             cur.close() 
  32.             conn.commit() 
  33.             conn.close() 
  34.             out_queue.task_done() 
  35. def main(): 
  36.     listDir('/data/logs/testlog/20120219/testlog1') 
  37.     for iq in range(in_num_thread): 
  38.         worker=Thread(target=readFile,args(iq,in_queue)) 
  39.         worker.setDaemon(True) 
  40.         worker.start() 
  41.     print "Readfile Main Thread Waiting at",ctime() 
  42.     in_queue.join()  
  43.     print "Readfile Done at,",ctime() 
  44.     for oq in range(out_num_thread): 
  45.         worker=Thread(target=writeLinestoDb,args(oq,out_queue)) 
  46.         worker.setDaemon(True) 
  47.         worker.start() 
  48.     print "Insert into mysql Main Thread at",ctime() 
  49.     out_queue.join()     
  50.     print "Insert into mysql at,",ctime() 
  51. if __name__=="__main__": 
  52.         print('starting at:',time.ctime()) 
  53.         main() 
  54.         print('ending at:',time.ctime()) 

 

 

  1. 数据库位于本机 
  2. ('starting at:', 'Tue Mar 27 10:57:01 2012')
    Readfile Main Thread Waiting at Tue Mar 27 10:57:01 2012
    Readfile Done at, Tue Mar 27 10:57:04 2012
    Insert into mysql Main Thread at Tue Mar 27 10:57:04 2012
    Insert into mysql at, Tue Mar 27 11:03:34 2012
    ('ending at:', 'Tue Mar 27 11:03:34 2012')
    mysql> select count(*) from log ;
    +----------+
    | count(*) |
    +----------+
    | 3676015 |
    +----------+
  3. 两次个数据不一致,多线的导入有问题
服务器配置4G8核,mysql本地 两个脚本在同一台机器上运行
多线程脚本改进
  1. #!/usr/bin/env python 
  2. #create table log ( logline varchar(300)); 
  3. #grant all on pythondata.* to 'pyuser'@'localhost' identified by "pypasswd"  
  4. import MySQLdb 
  5. import os 
  6. import sys 
  7. from time import ctime 
  8. from threading import Thread 
  9. from Queue import Queue 
  10.  
  11. num_thread=10 
  12. queue=Queue() 
  13.  
  14. def listDir(path): 
  15.         file_list=[] 
  16.         for filename in os.listdir(path): 
  17.                 file_list.append(os.path.join(path,filename)) 
  18.         return file_list 
  19.  
  20. def readFile(file): 
  21.         alllines=[] 
  22.         for line in open(file): 
  23.                 alllines.append(line) 
  24.         return alllines 
  25.  
  26. def writeLinestoDb(q,queue): 
  27.         sql=insertsql ="INSERT INTO log(logline) VALUES(%s)" 
  28.         while True: 
  29.                 content=queue.get() 
  30.                 conn=MySQLdb.connect(host="localhost",user="pyuser",passwd="pypasswd",db="pythondata") 
  31.                 cur =conn.cursor() 
  32.                 cur.executemany(sql,content) 
  33.                 cur.close() 
  34.                 conn.commit() 
  35.                 conn.close() 
  36.                 queue.task_done() 
  37.  
  38. def main(): 
  39.         print "Readfile Start at,",ctime() 
  40.         for file in listDir('/data/logs/testlog/20120219/testlog1'): 
  41.                 queue.put(readFile(file)) 
  42.         print "Readfile Done at,",ctime() 
  43.         for q in range(num_thread): 
  44.                 worker=Thread(target=writeLinestoDb,args=(q,queue)) 
  45.                 worker.setDaemon(True) 
  46.                 worker.start() 
  47.         print "Insert into mysql Main Thread at",ctime() 
  48.         queue.join() 
  49.         print "Insert into mysql at,",ctime() 
  50. if __name__=="__main__": 
  51.         print('starting at:',ctime()) 
  52.         main() 
  53.         print('ending at:',ctime()) 

 结果

('starting at:', 'Tue Mar 27 14:32:05 2012')
Readfile Start at, Tue Mar 27 14:32:05 2012
Readfile Done at, Tue Mar 27 14:32:07 2012
Insert into mysql Main Thread at Tue Mar 27 14:32:08 2012
Insert into mysql at, Tue Mar 27 14:34:31 2012
('ending at:', 'Tue Mar 27 14:34:31 2012')
mysql> select count(*) from log;
+----------+
| count(*) |
+----------+
| 1510551 |
+----------+

读用了2秒中,插入使用2分23秒

第一个多线程脚本错误的原因是传入队列的数据问题。 还有一个问题,读的文件超过物理内存和虚拟内存的总量,会造成内存溢出程序挂掉,解决办法每次读取指定行