【发布时间】:2018-09-28 09:38:26
【问题描述】:
当我遇到 MySQL 时,我遇到了一些麻烦。 我有一个存储车辆日志的表 deviceLog 包括: 1.设备ID 2.日期时间 3. 纬度 4. 经度
设备将每分钟将日志存储到数据库中。
这意味着一辆车每天有 1440 条记录。
假设我有 5000 辆汽车,那么每天表中将有大约 720 万行日志数据。
每个月我都需要生成每辆车的设备位置报告。这与另一个表名相关,即 POI (兴趣点),其中存储: 1. 地点名称 2. 纬度 3. 经度
的最终输出应该是: DeviceID、DateTimer、LocationName(根据deviceLog提供的纬度、经度)
对于 LocationName,我创建了一个调用存储过程的函数,通过发送行的纬度和经度来检索它,它将从 POI 表中返回 LocationName
CREATE DEFINER=`root`@`localhost` PROCEDURE `SPGetGeoName`(IN `xLat` DOUBLE, IN `xLon` DOUBLE, OUT `xLocationName` NVARCHAR(1500))
BEGIN
declare lon1 float; declare lon2 float;
declare lat1 float; declare lat2 float;
declare dist float; declare pi float;
set pi = 3.1415926;
set dist=1.9;
set lon1 = xLon-dist/abs(cos(radians(xLat))*69);
set lon2 = xLon+dist/abs(cos(radians(xLat))*69);
set lat1 = xLat-(dist/69); set lat2 = xLat+(dist/69);
SET xLocationName = (SELECT locationName FROM poiTest
WHERE longitude BETWEEN lon1 AND lon2 AND
latitude BETWEEN lat1 AND lat2 AND
3956 * 2 * ASIN(SQRT( POWER(SIN((xLat-latitude)* pi/180 / 2), 2) +COS(xLat*pi/180) * COS(latitude*pi/180) *POWER(SIN((xLon-longitude) * pi /180 / 2), 2) )) < dist
ORDER BY 3956 * 2 * ASIN(SQRT( POWER(SIN((xLat-latitude)* pi/180 / 2), 2) +COS(xLat*pi/180) * COS(latitude*pi/180) *POWER(SIN((xLon-longitude) * pi /180 / 2), 2) )) ASC limit 1);
END
结果如每辆车 15 秒 1 个月,粗略计算大约需要 1 天才能生成整个报告。
有没有办法克服这个问题?
CREATE TABLE `deviceLog` (
`tripID` int(11) NOT NULL AUTO_INCREMENT,
`latitude` float NOT NULL,
`longitude` double NOT NULL,
`rssi` smallint(6) NOT NULL,
`speed` float NOT NULL,
`course` float NOT NULL,
`hdop` float NOT NULL,
`dateTimer` datetime NOT NULL,
`gpsStat` tinyint(4) NOT NULL,
`unitStat` varchar(12) NOT NULL,
`battVolt` varchar(6) NOT NULL,
`fuelLevel` varchar(6) NOT NULL DEFAULT '0',
`fuelData` varchar(6) NOT NULL DEFAULT '0',
`ignVolt` varchar(6) NOT NULL,
`odoMeter` decimal(10,2) NOT NULL,
`deviceID` varchar(16) NOT NULL,
`chksum` varchar(2) NOT NULL,
`resol` varchar(1024) DEFAULT NULL,
`driverID` varchar(20) DEFAULT NULL,
`geoFences` varchar(255) DEFAULT NULL,
`poiLoc` varchar(255) DEFAULT NULL,
`eventStat` varchar(2) DEFAULT NULL,
`IOStat` varchar(4) DEFAULT NULL,
`groupID` varchar(2) DEFAULT NULL,
PRIMARY KEY (`tripID`),
KEY `deviceID` (`deviceID`),
KEY `dateTimer` (`dateTimer`)
) ENGINE=MyISAM AUTO_INCREMENT=3423023 DEFAULT CHARSET=latin1
CREATE TABLE `poi` (
`poiID` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(50) NOT NULL,
`locationName` varchar(200) NOT NULL,
`state` varchar(50) NOT NULL,
`city` varchar(50) NOT NULL,
`longitude` float(10,7) DEFAULT NULL,
`latitude` float DEFAULT NULL,
PRIMARY KEY (`poiID`),
KEY `lat` (`longitude`,`latitude`)
) ENGINE=MyISAM AUTO_INCREMENT=683606 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
【问题讨论】:
-
您的 POI 表中有多少条目?
-
嗨 Olli,大约有 550,000 个条目。
-
虽然数据库中的计算相当快,但一个想法可能是将一些已经预先计算的值(如果可能)存储到表本身并使用它们。它可能至少有一点帮助
-
与其给出答案,我建议不要为此目的使用 MySQL;既是因为您将遇到扩展问题,但主要是因为有专门为这种用例(物联网/流式传输/事件数据/时间序列)设计的专用技术堆栈。
-
感谢 Olli 的反馈,为了加快进程,我每天都会预先计算数据,例如:所有 2018 年 3 月 10 日之前的数据都会被处理以更新它们的位置。跨度>
标签: c# mysql performance bigdata latitude-longitude