一、问题分析
有两张表,一个是历史数据表,包含设备地理位置等信息;一个是部门表,每个设备对应一个部门。
网站前端的界面需要显示所有的历史数据和对应的部门,按照原来的左连接查询方法,在20万条数据前提下,结果查询时间为150s。因为在该方法下将主表的历史数据和副表进行联合查询,需要全表遍历,这种方案在数据量小的情况下可以实施,但是数据库表达到了几十万条后,就不再适用。
请记住,查询时间慢最基本原因是访问的数据太多。
二、解决方案
针对查询数据太多的问题,一般从以下两个方向入手:
- 应用程序检索大量超过需要的数据;
- MySQL服务器层分析大量超过需要的数据行;
导致上述问题的原因是第二个,网站前端只需要显示前10条、前20条、 … 、前90条。而先连接再分页导致每一行主表记录都要关联副表,最后只要前10*N条,MySQL服务器层分析大量超过需要的数据行。
而解决MySQL服务器层分析大量超过需要的数据行的问题,从以下几个指标进行衡量:
- 响应时间(快速上线估计值)
- 扫描的行数
- 返回的行数
得到数据集的方式有几种,和访问类型有关,访问类型依次从慢到快有以下几种,扫描的行数也是依次递减:
- 全表扫描
- 索引扫描
- 范围扫描
- 唯一索引查询
- 常数引用
更改方案后,采用先分页(即限制主表查询的条数:Limit 0,10)再查询的方法,时间缩短至3s。但是这也引入了其它问题。
三、引入其它问题
主表限制后,当根据副表的某个字段(如部门)进一步限制后,查询到的数据条目不存在,这显然和预期的不一致。这个在设计表时也有关系,如果在主表里增加了该字段就不会出现这种问题。
四、解决引入的问题
针对上述问题,根据不同的限制条件进行不同的方法的查询。出现了三种情况。如下表所示,0表示空,1表示有。
设备号 | 部门 | 查询方法 |
0 | 0 | 方法1(先对历史数据表分页,再左连接部门表) |
1 | 0 | 方法1(先对历史数据表分页,再左连接部门表) |
0 | 1 | 方法2 (先对设备表分页,再左连接历史数据表) |
1 | 1 | 方法3(先查出部门拥有的设备,再左连接历史数据表) |
五、MySQL的一些性能数据指标(通用服务器)
- 能够每秒查询10万条数据
- 2000 QPS