老司机大型车祸现场
就在本周,应该是在本周二,小编翻车啦~~~
之前有关注我的同学应该知道,小编在国庆节写了一只爬虫,来抓取自己的各个平台博客的访问量等一些数据,并且后面简单做了个报表,主要是靠 SQL 来统计数据。
这只爬虫小编部署到 Linux 服务器上以后,设置了整点定时抓取数据也没管过,倒是刚上线那段时间经常去报表平台看看统计报表。
肯定哪里不对,小编赶紧用 Navicat 执行了一下报表的 SQL ,结果:
对的,你没看错,这句话执行了 20s+ ,小编当时的心里感觉有一万只羊驼奔腾而过。
有没有搞错,数据拢共 2k 多条,执行一下要 20s+ ,是在开玩笑么,小编当时都怀疑自己是不是用了一台假数据库。
emmmmmmmmmm,顺便介绍一下数据库配置,使用的是某云服务的 MySQL 库,硬件配置为 1H1G(1核1G)。
冷静下,深呼吸两个,小编不信邪,正好手上有一台 2H8G 的服务器,赶紧搭一个 Mysql 试一下,某云提供的一定是假数据库。
结果,emmmmmmmmmmm,还是直接给各位同学看吧。
好吧,现在要正式这个错误。。。
不过服务器的核心数加了一倍(一个)时间数少了一半多,那理论上讲,如果小编用的是一台物理机,如果这台物理机有大几十核的 CPU ,就不会有问题啊~~~
果然,还是贫穷惹的祸。。。。
告辞。
当然,本文不会就这么结束:)
现在,已经发现错误了,接下来就是尤为关键的一步了,解决这个问题。
程序猿解决问题是有一个万能的模版,先用这个模版套一下:
- 这不是个问题,所以不用解决。
- 将提问题的人解决掉。
emmmmmmmmmm,提问题的人是小编自己,所以,小编不能解决掉自己,那么,这就不是个问题,所以也就不需要解决了。。。。。。。。
不行,这个还是太影响使用体验,还是来正经的分析下这个问题。
首先看下数据库的表设计:
咳咳。
就这么一张表,当时比较懒,爬虫每次抓取的都是当时的截面数据,统计报表的 sql 需要动态的去算出每天的增量数据。具体算法是使用当天的最大值减去前一天的最大值,再进行分类统计。
看下小编的 sql 吧:
SELECT a.read_num - ( SELECT b.read_num FROM spider_data b WHERE b.plantform = a.plantform AND DATE_FORMAT(b.create_date, '%Y-%m-%d') = date_sub(DATE_FORMAT(a.create_date, '%Y-%m-%d'), INTERVAL 1 DAY) ORDER BY b.create_date DESC LIMIT 1 ) AS read_num, a.fans_num - ( SELECT b.fans_num FROM spider_data b WHERE b.plantform = a.plantform AND DATE_FORMAT(b.create_date, '%Y-%m-%d') = date_sub(DATE_FORMAT(a.create_date, '%Y-%m-%d'), INTERVAL 1 DAY) ORDER BY b.create_date DESC LIMIT 1 ) AS fans_num , a.like_num - ( SELECT b.like_num FROM spider_data b WHERE b.plantform = a.plantform AND DATE_FORMAT(b.create_date, '%Y-%m-%d') = date_sub(DATE_FORMAT(a.create_date, '%Y-%m-%d'), INTERVAL 1 DAY) ORDER BY b.create_date DESC LIMIT 1 ) AS like_num, ( SELECT b.rank_num FROM spider_data b WHERE b.plantform = a.plantform AND DATE_FORMAT(b.create_date, '%Y-%m-%d') = date_sub(DATE_FORMAT(a.create_date, '%Y-%m-%d'), INTERVAL 1 DAY) ORDER BY b.create_date DESC LIMIT 1 ) - a.rank_num AS rank_num , a.create_date,a.plantform FROM (SELECT * FROM spider_data ORDER BY create_date DESC LIMIT 1000000000000000) a GROUP BY DATE_FORMAT(a.create_date, '%Y-%m-%d'), a.plantform ORDER BY a.create_date DESC;
稍微长了一丢丢,不过从这个 sql 上,已经能看到明显的问题了,在做查询的时候,使用了大量的子查询。
至于为什么要这么写,当然是因为懒咯~~~
前面的爬虫已经将截面数据爬取到了,后面做统计当然是一句话搞定了。
结果就是这偷懒的一句话,酿造了今天的惨剧。