问题: 项目每日游戏日志表数据量由原来1w+增长到千万级别,原先获取数据方式:

SELECT * FROM table

一次性取出的数据量太大导致内存溢出。既然一次性取数据不行,那就分次处理~
 
1-1. 使用LIMIT每次取5w条数据

SELECT * FROM table LIMIT 0,50000SELECT * FROM table LIMIT 50000,50000...

重新跑了代码,速度很慢,可能是处理数据耗时过长,数据表内有一大部分是此处无用的重复数据,从这入手~
 
1-2. 根据项目情况通过SELECT DISTINCT减少得到的数据量
加上索引后速度不错,但是INDEX_LENGTH大约是DATA_LENGTH的75%左右。
索引占了太大空间,只能另想他法 ╮(╯▽╰)╭
 
发现一个奇怪现象:

SELECT * FROM table LIMIT 0,50000 #速度很快SELECT * FROM table LIMIT 5000000,50000 #速度很慢


此表有自增id主键,所以使用WHERE条件可以顺利解决~
 
1-3. 通过WHERE条件按自增id取数据

SELECT * FROM table WHERE id > 0 AND id <= 50000SELECT * FROM table WHERE id > 50000 AND id <= 100000...


搞定~ 但是还有一个模块需要使用其它查询条件,最终结果id不连续,得另想个办法。
 
基于:

SELECT * FROM table LIMIT 5000000,1 #速度相对较快SELECT * FROM table LIMIT 5000000,50000 #速度很慢


2-1. 先取第一条id 再通过id与LIMIT取数据

SELECT * FROM table WHERE condition AND id >= (SELECT id FROM table WHRER condition LIMIT 5000000,1) LIMIT 50000

速度提升,但不理想。
 
2-2. 先通过子查询取出id 再通过id取数据

SELECT * FROM table WHERE id IN (SELECT id FROM (SELECT id FROM table WHERE condition LIMIT 5000000,50000) AS tmp)

先通过主键索引找出id,再通过id取数据,测试结果不理想,但是SQL和子查询分开执行,速度ok。
 
2-3. 拆分成两次执行 先取出id 再通过id取数据

SELECT id FROM table WHERE condition #先取出并处理idSELECT * FROM table WHERE id IN (5000001,5000002,5000003,...)

速度可以接受,使用其它条件不通过索引查询速度相对还会慢一些,模块内每个字段都可以作为组合查询条件,所以没加索引,在项目页面上增加先缩小数据范围再查询的提示,搞定~