需求:系统对接了厂家的GPS数据,基于这些GPS数据,过滤出指定区域的数据

从网上找到了一个电子围栏的python脚本,现在需要的是循环取数据判断是否在指定区域,在指定区域就把这部分数据拿出来放到另外一个库表

1、效率问题

碰到的其中一个问题是脚本的效率问题,以5W条数据来测试

脚本1:使用cur.fetchone(),逐条读取数据,逐条判断,逐条插入列表,批量入库,批量commit

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import json

import math

import MySQLdb

import time

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"广本黄埔工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

conn=MySQLdb.connect(user='root',passwd='XXX',host='XXX',charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db('XXX')

cur.execute("select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no from gps_msg where sample_time>='2019-04-10 18:00:00' and sample_time

####################第一种方式########################

count=1

scope_gps_list=[]

while count<=50000: #这种方式,这个数量不能比SQL的数据量小,不然会报错

gps_data_per=cur.fetchone()

# print gps_data_per

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

# print point

# print count

if count in(10000,20000,30000,40000,50000):

print count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

# print windingNumber(point,lnglatlist)

if windingNumber(point,lnglatlist)=='in':

scope_gps_list.append(gps_data_per) #生成[(1,2,3),(1,2,3)]

count=count+1

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

cur.executemany(sqlin,scope_gps_list)

conn.commit()

####################第一种方式########################

####################第二种方式########################

# gps_data_all=cur.fetchall()

# count=0

# for gps_data_per in gps_data_all:

# sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

# point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

# point=map(float,point) #字符串类型转换成浮点型

# if windingNumber(point,lnglatlist)=='in':

# cur.execute(sqlin,gps_data_per)

# count=count+1

# print count

# conn.commit()

####################第二种方式########################

cur.close() #关闭游标

conn.close() #关闭数据链接

################循环取GPS数据##########################

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())View Code

为什么要逐条插入列表?

因为使用cur.fetchone()读取数据后马上去insert into数据,再次cur.fenchone数据,取不到数据

执行效率:30分6秒跑完

start : 2019-04-19 20:30:00

10000 : 2019-04-19 20:31:16        1分16秒

20000 : 2019-04-19 20:34:56        3分40秒

30000 : 2019-04-19 20:41:03        6分6秒

40000 : 2019-04-19 20:49:35        8分32秒

50000 : 2019-04-19 21:00:36        11分1秒

end : 2019-04-19 21:00:36            不到一秒

总结:最后的列表插入数据库很快,不到1秒

脚本2:使用cur.fetchall()先存全部数据,再使用for循环,逐条读取,逐条判断,逐条入库,批量commit

对比脚本1,主要是逐条入库,避免插入到列表,确定下是否插入到列表,列表越来越大导致的慢

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import json

import math

import MySQLdb

import time

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

conn=MySQLdb.connect(user='root',passwd='XXX',host='XXX',charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db('XXX')

cur.execute("select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no from gps_msg where sample_time>='2019-04-10 18:00:00' and sample_time

####################第一种方式########################

# count=1

# scope_gps_list=[]

# while count<=50000: #这种方式,这个数量不能比SQL的数据量小,不然会报错

# gps_data_per=cur.fetchone()

# point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

# point=map(float,point) #字符串类型转换成浮点型

# if count in(10000,20000,30000,40000,50000):

# print count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

# if windingNumber(point,lnglatlist)=='in':

# scope_gps_list.append(gps_data_per) #生成[(1,2,3),(1,2,3)]

# count=count+1

# sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

# cur.executemany(sqlin,scope_gps_list)

# conn.commit()

####################第一种方式########################

####################第二种方式########################

gps_data_all=cur.fetchall()

count=0

for gps_data_per in gps_data_all:

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per)

count=count+1

if count in(10000,20000,30000,40000,50000):

print count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

conn.commit()

####################第二种方式########################

cur.close() #关闭游标

conn.close() #关闭数据链接

################循环取GPS数据##########################

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())View Code

执行效率:29分钟22秒

start : 2019-04-19 21:05:09

10000 : 2019-04-19 21:06:22    1分16秒

20000 : 2019-04-19 21:09:55    3分33秒

30000 : 2019-04-19 21:15:48    5分53秒

40000 : 2019-04-19 21:23:58    8分10秒

50000 : 2019-04-19 21:34:31    10分33秒

end : 2019-04-19 21:34:31        不到1秒

总结,看来不是插入到列表,导致的速度慢

脚本3:使用cur.fetchall()先存全部数据,再使用for循环,逐条读取,逐条判断,逐条入库,逐条commit

对比脚本2,逐条入库,逐条commit,只是做个简单的对比

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import json

import math

import MySQLdb

import time

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

conn=MySQLdb.connect(user='root',passwd='XXX',host='XXX',charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db('XXX')

cur.execute("select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no from gps_msg where sample_time>='2019-04-10 18:00:00' and sample_time

####################第一种方式########################

# count=1

# scope_gps_list=[]

# while count<=50000: #这种方式,这个数量不能比SQL的数据量小,不然会报错

# gps_data_per=cur.fetchone()

# point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

# point=map(float,point) #字符串类型转换成浮点型

# if count in(10000,20000,30000,40000,50000):

# print count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

# if windingNumber(point,lnglatlist)=='in':

# scope_gps_list.append(gps_data_per) #生成[(1,2,3),(1,2,3)]

# count=count+1

# sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

# cur.executemany(sqlin,scope_gps_list)

# conn.commit()

####################第一种方式########################

####################第二种方式########################

gps_data_all=cur.fetchall()

count=0

for gps_data_per in gps_data_all:

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per)

conn.commit()

count=count+1

if count in(10000,20000,30000,40000,50000):

print count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

####################第二种方式########################

cur.close() #关闭游标

conn.close() #关闭数据链接

################循环取GPS数据##########################

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())View Code

执行效率:30分1秒

start : 2019-04-19 21:45:11

10000 : 2019-04-19 21:46:30    1分19秒

20000 : 2019-04-19 21:50:10    3分40秒

30000 : 2019-04-19 21:56:09    5分59秒

40000 : 2019-04-19 22:04:30    8分21秒

50000 : 2019-04-19 22:15:12    10分42秒

end : 2019-04-19 22:15:12        不到1秒

总结:逐条commit会降低效率,但是不会太多

脚本4:前面执行10000条数据的时候都很快,后面越来越慢,尝试按时间点分段执行SQL,这次的数据范围为一个小时,数据量6W多条,如果效率提高,按5分钟分段,分12次执行,每次的SQL数据量只有5600多行,再使用for循环,逐条读取,逐条判断,逐条入库,逐条commit

对比脚本1,2,3,试下按时间点分段执行SQL的效率,如果效率有提升,总时间应该=执行一次的时间*12

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import json

import math

import MySQLdb

import time

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

conn=MySQLdb.connect(user='XXX',passwd='XXX',host='XXX',charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db('XXX')

####################第三种方式########################

def TO_DB(sample_time_start,sample_time_end):

sql="""

select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no

from gps_msg

where sample_time>="""+"'"+sample_time_start+"'"+"and sample_time

cur.execute(sql)

gps_data_all=cur.fetchall()

# count=0

for gps_data_per in gps_data_all:

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per)

conn.commit()

count=1

sample_time_hour='2019-04-10 18:'

sample_time_hour_next='2019-04-10 19:'

for sample_time_min_start in range(0,60,5):

if count <12:

sample_time_min_end=sample_time_min_start+5

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour+str(sample_time_min_end)

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

else:

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour_next+'0'

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

count=count+1

####################第三种方式########################

cur.close() #关闭游标

conn.close() #关闭数据链接

################循环取GPS数据##########################

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())

View Code

执行效率:执行超过了30分钟,很明显此方式也行不通

执行了9次,大概执行了5W条数据,耗时29分11秒,一样的,越到后面越慢。

start : 2019-04-20 10:34:28

2019-04-10 18:0 2019-04-10 18:5 1 : 2019-04-20 10:34:56                 28秒

2019-04-10 18:5 2019-04-10 18:10 2 : 2019-04-20 10:36:10               1分14秒

2019-04-10 18:10 2019-04-10 18:15 3 : 2019-04-20 10:38:13             2分3秒

2019-04-10 18:15 2019-04-10 18:20 4 : 2019-04-20 10:41:02             2分49秒

2019-04-10 18:20 2019-04-10 18:25 5 : 2019-04-20 10:44:33             3分31秒

2019-04-10 18:25 2019-04-10 18:30 6 : 2019-04-20 10:48:42             4分12秒

2019-04-10 18:30 2019-04-10 18:35 7 : 2019-04-20 10:53:14             4分32秒

2019-04-10 18:35 2019-04-10 18:40 8 : 2019-04-20 10:58:09             4分55秒

2019-04-10 18:40 2019-04-10 18:45 9 : 2019-04-20 11:03:39             5分30秒

总结:效率还是不行

脚本5:在脚本4的基础上修改下,按时间点分段执行SQL,不同的是,执行完一次SQL就关闭连接,再重新打开一个连接执行下一个SQL

对比脚本4,看下是不是一个连接一直执行效率会越来越低

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import json

import math

import MySQLdb

import time

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

####################第三种方式########################

def TO_DB(sample_time_start,sample_time_end):

conn=MySQLdb.connect(user=XXX,passwd=XXX,host=XXX,charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db(XXX)

sql="""

select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no

from gps_msg

where sample_time>="""+"'"+sample_time_start+"'"+"and sample_time

cur.execute(sql)

gps_data_all=cur.fetchall()

# count=0

for gps_data_per in gps_data_all:

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per)

conn.commit()

cur.close() #关闭游标

conn.close() #关闭数据链接

count=1

sample_time_hour='2019-04-10 18:'

sample_time_hour_next='2019-04-10 19:'

for sample_time_min_start in range(0,60,5):

if count <12:

sample_time_min_end=sample_time_min_start+5

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour+str(sample_time_min_end)

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

else:

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour_next+'0'

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

count=count+1

# count=count+1

# if count in(10000,20000,30000,40000,50000):

# print count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

####################第三种方式########################

################循环取GPS数据##########################

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())

View Code

执行效率:执行超过了30分钟,很明显此方式也行不通

执行到了9次,大概执行了5W条数据,耗时28分54秒,一样的,越到后面越慢。全部执行完,花费了48分50秒

start : 2019-04-20 11:10:35

2019-04-10 18:0 2019-04-10 18:5 1 : 2019-04-20 11:11:03                    28秒

2019-04-10 18:5 2019-04-10 18:10 2 : 2019-04-20 11:12:17                  1分14秒

2019-04-10 18:10 2019-04-10 18:15 3 : 2019-04-20 11:14:19                 2分2秒

2019-04-10 18:15 2019-04-10 18:20 4 : 2019-04-20 11:17:07                 2分48秒

2019-04-10 18:20 2019-04-10 18:25 5 : 2019-04-20 11:20:37                 3分30秒

2019-04-10 18:25 2019-04-10 18:30 6 : 2019-04-20 11:24:42                 4分5秒

2019-04-10 18:30 2019-04-10 18:35 7 : 2019-04-20 11:29:12                 4分30秒

2019-04-10 18:35 2019-04-10 18:40 8 : 2019-04-20 11:34:03                 4分51秒

2019-04-10 18:40 2019-04-10 18:45 9 : 2019-04-20 11:39:29                 5分26秒

2019-04-10 18:45 2019-04-10 18:50 10 : 2019-04-20 11:45:26               5分57秒

2019-04-10 18:50 2019-04-10 18:55 11 : 2019-04-20 11:52:16               6分50秒

2019-04-10 18:55 2019-04-10 19:0 12 : 2019-04-20 11:59:25                 7分9秒

end : 2019-04-20 11:59:25

总结:还是存在越到后面越慢的问题

脚本6:使用profile工具工具进行检查

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from cProfile import Profile

import json

import math

import MySQLdb

import time

import gc

import thread

# from numba import jit

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

####################第三种方式########################

def TO_DB(sample_time_start,sample_time_end):

conn=MySQLdb.connect(user='XXX',passwd='XXX',host='XXX',charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db('XXX')

sql="""

select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no

from gps_msg

where sample_time>="""+"'"+sample_time_start+"'"+"and sample_time

cur.execute(sql)

gps_data_all=cur.fetchall()

# count=0

for gps_data_per in gps_data_all:

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per)

conn.commit()

# del point #释放变量,没啥用

# gc.collect()

cur.close() #关闭游标

conn.close() #关闭数据链接

def for_exec():

count=1

sample_time_hour='2019-04-10 18:'

sample_time_hour_next='2019-04-10 19:'

for sample_time_min_start in range(0,10,5):

if count <12:

sample_time_min_end=sample_time_min_start+5

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour+str(sample_time_min_end)

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

else:

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour_next+'0'

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

count=count+1

####################第三种方式########################

################循环取GPS数据##########################

if __name__ == '__main__':

prof = Profile()

prof.runcall(for_exec)

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())

prof.print_stats()

# prof.dump_stats('test.prof') # dump profile result to test.prof

结果:输出的结果如下,for_exec里面包含TO_DB,TO_DB里面包含windingNumber

每个字段(和上面截图一一对应)的含义如下:ncalls 函数总的调用次数

tottime 函数内部(不包括子函数)的占用时间

percall(第一个) tottime/ncalls

cumtime 函数包括子函数所占用的时间

percall(第二个)cumtime/ncalls

filename:lineno(function)  文件:行号(函数)

基于上面字段的理解分析,逻辑上看,判断出来主要是windingNumber函数耗时,如下for_exec里面包含TO_DB,TO_DB里面包含windingNumber

for_exec和TO_DB的tottime很少,cumtime挺大,windingNumber的tottime和cumtime都挺大(tottime和cumtime相差的时间如下)

脚本7:安装numba模块,进行加速

安装numba模块,使用pip install numba,安装失败

尝试使用conda包管理工具进行安装,如下参考

使用命令,针对2.7的python,使用如下链接下载后安装

https://repo.anaconda.com/archive/Anaconda2-2019.03-Linux-x86_64.sh --no-check-certificate

安装完后修改脚本,如下,再次执行测试

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from cProfile import Profile

import json

import math

import MySQLdb

import time

import gc

import thread

from numba import jit

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

@jit

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

####################第三种方式########################

# @jit

def TO_DB(sample_time_start,sample_time_end):

conn=MySQLdb.connect(user='XXX',passwd='XXX',host='XXX',charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db('XXX')

sql="""

select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no

from gps_msg

where sample_time>="""+"'"+sample_time_start+"'"+"and sample_time

cur.execute(sql)

gps_data_all=cur.fetchall()

# count=0

for gps_data_per in gps_data_all:

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per)

conn.commit()

# del point #释放变量,没啥用

# gc.collect()

cur.close() #关闭游标

conn.close() #关闭数据链接

# @jit

def for_exec():

count=1

sample_time_hour='2019-04-10 18:'

sample_time_hour_next='2019-04-10 19:'

for sample_time_min_start in range(0,60,5):

if count <12:

sample_time_min_end=sample_time_min_start+5

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour+str(sample_time_min_end)

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

else:

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour_next+'0'

TO_DB(sample_time_start,sample_time_end)

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

count=count+1

####################第三种方式########################

################循环取GPS数据##########################

for_exec()

# if __name__ == '__main__':

# prof = Profile()

# prof.runcall(for_exec)

# print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())

# prof.print_stats()

# prof.dump_stats('test.prof') # dump profile result to test.prof

对比下脚本5,看下效率,总共花了40分39秒

节省了8分11秒

通过以上的种种办法,还是存在越到后面,数据处理会越来越慢的情况,于是继续尝试

脚本8:按时间点执行分批次执行SQL,使用子进程执行,每次执行都是不同的子进程

以下红色为对比脚本7添加的代码

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from cProfile import Profile

import json

import math

import MySQLdb

import time

import gc

import thread

from numba import jit

from multiprocessing import Process

ISOTIMEFORMAT='%Y-%m-%d %X'

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

@jit

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

################循环取GPS数据##########################

####################第三种方式########################

# @jit

def TO_DB(sample_time_start,sample_time_end):

conn=MySQLdb.connect(user='XXX',passwd='XXX',host='XXX',charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db('XXX')

sql="""

select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no

from gps_msg

where sample_time>="""+"'"+sample_time_start+"'"+"and sample_time

cur.execute(sql)

gps_data_all=cur.fetchall()

# count=0

for gps_data_per in gps_data_all:

sqlin="insert into gps_msg_20190411(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per)

conn.commit()

# del point #释放变量,没啥用

# gc.collect()

cur.close() #关闭游标

conn.close() #关闭数据链接

# @jit

def for_exec():

count=1

sample_time_hour='2019-04-10 18:'

sample_time_hour_next='2019-04-10 19:'

for sample_time_min_start in range(0,60,5):

if count <12:

sample_time_min_end=sample_time_min_start+5

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour+str(sample_time_min_end)

# TO_DB(sample_time_start,sample_time_end)

p=Process(target=TO_DB,args=(sample_time_start,sample_time_end,))

p.start()

p.join()

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

else:

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour_next+'0'

# TO_DB(sample_time_start,sample_time_end)

p=Process(target=TO_DB,args=(sample_time_start,sample_time_end,))

p.start()

p.join()

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime())

count=count+1

####################第三种方式########################

################循环取GPS数据##########################

for_exec()

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())

# if __name__ == '__main__':

# prof = Profile()

# prof.runcall(for_exec)

# print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())

# prof.print_stats()

# prof.dump_stats('test.prof') # dump profile result to test.prof

执行效率:4分15秒

使用此方法,成功,每次执行时间基本相同,看来原因是在一个进程执行导致。

如果去掉numba,效率会降低多少?测试了下,去掉numba,执行效率:4分28秒,也没降低多少。

另外还有一种方法可以比较实时地抓取超速数据,可以分批次,多频次执行脚本,每次脚本执行处理较少数据。可以使用crontab调度,每分钟执行一次,只执行1分钟的数据,因为数据量比较小,基本3秒完成。

脚本9:使用多进程,按时间点,分批次执行SQL

脚本如下:红色表示为多进程使用到的语句

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from cProfile import Profile

import json,os

import math

import MySQLdb

import time

import gc

import thread

from numba import jit

from multiprocessing import Process

from multiprocessing import Pool

import datetime

ISOTIMEFORMAT='%Y-%m-%d %X'

start=time.time()

print 'start',':',time.strftime(ISOTIMEFORMAT, time.localtime())

lnglatlist = []

data = '[{"name":"工厂","points":[{"lng":113.642124,"lat":23.167372},{"lng":113.636176,"lat":23.175162},{"lng":113.644930,"lat":23.179870},{"lng":113.652108,"lat":23.173823}],"type":0}]'

data = json.loads(data)

if 'points' in data[0]:

for point in data[0]['points']:

#print(str(point['lng'])+" "+str(point['lat']))

lnglat = []

lnglat.append(float(str(point['lng'])))

lnglat.append(float(str(point['lat'])))

lnglatlist.append(lnglat)

# @jit

def windingNumber(point, poly):

poly.append(poly[0])

px = point[0]

py = point[1]

sum = 0

length = len(poly)-1

for index in range(0,length):

sx = poly[index][0]

sy = poly[index][1]

tx = poly[index+1][0]

ty = poly[index+1][1]

#点与多边形顶点重合或在多边形的边上

if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):

return "on"

#点与相邻顶点连线的夹角

angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)

#确保夹角不超出取值范围(-π 到 π)

if(angle >= math.pi):

angle = angle - math.pi * 2

elif(angle <= -math.pi):

angle = angle + math.pi * 2

sum += angle

#计算回转数并判断点和多边形的几何关系

result = 'out' if int(sum / math.pi) == 0 else 'in'

return result

print 'test',result

################循环取GPS数据##########################

####################第三种方式########################

mysql_host='XXX'

mysql_database='XXX'

mysql_user='XXX'

mysql_passwd='XXX'

def delete_data(sample_time_start):

sample_time_end=datetime.datetime.strftime(datetime.datetime.strptime(sample_time_start, "%Y-%m-%d %H")+datetime.timedelta(hours=1), '%Y-%m-%d %H')

conn=MySQLdb.connect(user=mysql_user,passwd=mysql_passwd,host=mysql_host,charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db(mysql_database)

sql_delete="""

delete from gps_msg_test

where sample_time>="""+"'"+sample_time_start+"'"+"and sample_time

cur.execute(sql_delete)conn.commit()

cur.close() #关闭游标

conn.close() #关闭数据链接

def TO_DB(sample_time_start,sample_time_end):

conn=MySQLdb.connect(user=mysql_user,passwd=mysql_passwd,host=mysql_host,charset="utf8") #连接到mysql

cur=conn.cursor()

conn.select_db(mysql_database)

sql="""

select id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no

from gps_msg

where sample_time>="""+"'"+sample_time_start+"'"+"and sample_time

conn.commit()

cur.execute(sql)

gps_data_all=cur.fetchall()

for gps_data_per in gps_data_all:

gps_data_per_list=list(gps_data_per) #转为列表

gps_data_per_list.append('XX厂区')

sqlin="insert into gps_msg_test(id,sim,alarm,status,latitude,longitude,asl,speed,direction,sample_time,attch_msg,create_time,car_no,location) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"

point=gps_data_per[5].split(",")+gps_data_per[4].split(",") #取出每条数据的经纬度,split()转换成列表

point=map(float,point) #字符串类型转换成浮点型

if windingNumber(point,lnglatlist)=='in':

cur.execute(sqlin,gps_data_per_list)

conn.commit()

cur.close() #关闭游标

conn.close() #关闭数据链接

############################################SQL分段执行#################################################

def for_exec(sample_time_hour):

count=1

interval=1 #执行的间隔

number=60/interval #执行的次数

sample_time_hour=sample_time_hour+':'

# sample_time_hour_next='2019-04-10 19:'

sample_time_hour_next=datetime.datetime.strftime(datetime.datetime.strptime(sample_time_hour, "%Y-%m-%d %H:")+datetime.timedelta(hours=1), '%Y-%m-%d %H:')

p = Pool(60) #创建进程池

for sample_time_min_start in range(0,60,interval):

if count

sample_time_min_end=sample_time_min_start+interval #分钟处的结算时间

sample_time_start=sample_time_hour+str(sample_time_min_start) #开始时间,第一次执行:2019-04-10 18:0

sample_time_end=sample_time_hour+str(sample_time_min_end) #结束时间,第一次执行:2019-04-10 18:1

p.apply_async(TO_DB,args=(sample_time_start,sample_time_end,))

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime()),os.getpid()

else:

sample_time_start=sample_time_hour+str(sample_time_min_start)

sample_time_end=sample_time_hour_next+'0'

p.apply_async(TO_DB,args=(sample_time_start,sample_time_end,))

print sample_time_start,sample_time_end,count,':',time.strftime(ISOTIMEFORMAT, time.localtime()),os.getpid()

count=count+1

p.close()

p.join()

############################################SQL分段执行#################################################

####################第三种方式########################

################循环取GPS数据##########################

gps_time='2019-04-10 18' #执行的时间点

delete_data(gps_time)

for_exec(gps_time)

print 'end',':',time.strftime(ISOTIMEFORMAT, time.localtime())

end=time.time()

print end-start

效率:耗时1秒多搞定

注:如果不指定进程的话,pool的默认大小是CPU的核数

2、坐标转换

标准坐标转火星坐标:https://lbs.amap.com/api/webservice/guide/api/convert

火星坐标转标准坐标:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import math

def GCJ2WGS(lon,lat):

a = 6378245.0

ee = 0.00669342162296594323

PI = 3.14159265358979324

x = lon - 105.0

y = lat - 35.0

dLon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x))

dLon += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0

dLon += (20.0 * math.sin(x * PI) + 40.0 * math.sin(x / 3.0 * PI)) * 2.0 / 3.0

dLon += (150.0 * math.sin(x / 12.0 * PI) + 300.0 * math.sin(x / 30.0 * PI)) * 2.0 / 3.0

dLat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x))

dLat += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0

dLat += (20.0 * math.sin(y * PI) + 40.0 * math.sin(y / 3.0 * PI)) * 2.0 / 3.0

dLat += (160.0 * math.sin(y / 12.0 * PI) + 320 * math.sin(y * PI / 30.0)) * 2.0 / 3.0

radLat = lat / 180.0 * PI

magic = math.sin(radLat)

magic = 1 - ee * magic * magic

sqrtMagic = math.sqrt(magic)

dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);

dLon = (dLon * 180.0) / (a / sqrtMagic * math.cos(radLat) * PI);

wgsLon = lon - dLon

wgsLat = lat - dLat

return wgsLon,wgsLat

print(GCJ2WGS(113.65723,23.171041))

print("Done!")

mysql 围栏_一个电子围栏需求的脚本记录相关推荐

  1. .net mysql 工作流_一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core

    一.关于Workflow-Core 近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完 ...

  2. mysql 围栏_地理围栏

    地理围栏技术 本词条缺少信息栏.名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 地理围栏(Geo-fencing)是LBS的一种新应用,就是用一个虚拟的栅栏围出一个虚拟地理边界.当手机 ...

  3. excel转mysql 工具_一个简单的批量excel转mysql工具

    背景:工作中,经常发现需要将excel中的表数据导入到mysql中,实际操作一般都是用navcat,但是使用中也发现navcat只支持单个表导入,对xlsx格式支持不友好.于是写了这么一个导表工具.在 ...

  4. php简单的mysql类_一个简单的php mysql操作类

    本文分享一个简单的php.mysql操作类,很简单,主要是数据的连接.查询等.有需要的朋友参考下吧. 分享一段php.mysql操作类的代码,供初学的朋友参考. 一个简单的类使用php和mysql数据 ...

  5. 怎么抽象mysql数据库_一个用于mysql的数据库抽象层函数库

    一个用于mysql的数据库抽象层函数库 更新时间:2006年10月09日 00:00:00   作者: // // SourceForge: Breaking Down the Barriers to ...

  6. 一个机器能装两个mysql吗_一个机器安装多个mysql

    /home/setup/mysql-5.0.96 grep config config.status :查看mysq的编译参数 './configure'  '–prefix=/usr/local/m ...

  7. mysql浏览器_一个简单的MySQL数据浏览器

    一个简单的MySQL数据浏览器 更新时间:2006年10月09日 00:00:00   作者: 这个程序可以用来浏览MySQL中的数据,您可以稍做修改就可以做出很不错的MySQL浏览器. */ /* ...

  8. 腾讯云mysql架构_一个数据库存储架构的独白

    本文由云+社区发表 本文作者:许中清,腾讯云自研数据库CynosDB的分布式存储CynosStore负责人.从事数据库内核开发.数据库产品架构和规划.曾就职于华为,2015年加入腾讯,参与过TBase ...

  9. python socket发包_一个python发包的脚本

    #coding=utf-8 ''' Created on 2016年4月12日 @author: administrater ''' from socket import * import time ...

最新文章

  1. 降低数值精度以提高深度学习性能
  2. C++ 对TXT 的串并行读写
  3. React开发(123):ant design学习指南之form中的属性isFieldTouched
  4. airpods2突然变得很小声_11岁女孩胸部发育被同学取笑,穿束胸衣上课突然晕倒...
  5. android统计流量,Android 获取手机整体流量使用情况以及某个应用的流量的统计
  6. Java Android 代码片段收集
  7. atitit.流程标准化--- mysql启动不起来的排查流程attilax总结
  8. 将 Ps 的调色效果保存为预设文件
  9. Matlab带阻滤波器实验报告,有源滤波器实验报告
  10. 二倍图三倍图什么意思_iOS开发中的二倍图、三倍图
  11. 可视化神器Plotly玩转直方图
  12. python网易公开课官网_可汗学院公开课:计算机科学
  13. 利用支付宝短信服务接口 实现手机号 验证码登录Demo
  14. 2023-2028年中国硫氰酸钠市场发展动态及前景预测报告
  15. css 如何选择同一个class下的第一个div?
  16. 【译】LiveData三连
  17. 《Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks》论文翻译
  18. 算法笔记(1)-常用推荐算法总结
  19. 蓝牙麦克风 android,带有蓝牙麦克风的Android语音识别器
  20. Bitmap的图片压缩汇总

热门文章

  1. 关于Selenium启动Chrome浏览器闪退问题
  2. Linux打印一个文字logo
  3. 适合零基础学习Python的书籍
  4. 关于git的使用(十五)------Rebase
  5. 一滴水泛起行业波纹,惠民保给保险业带来的启示录
  6. HTML学习6~29(HTML语法规范)
  7. Prometheus 实战于源码分析之storage
  8. ORACLE 各类博客
  9. 【设计模式】依赖倒转原则(Dependence Inversion Principle)
  10. 数据结构13:无序表抽象数据类型(链表)(一)