MySQL千萬級數據的全表掃描優化

數據場景

一個很簡單 的業務數據表,2300W規模的數據,沒有複雜數據類型,不想分表,還需要全表遍歷

Select全表性能

  • 查詢接口
    @Mapper
    public interface UserMapper {
        @Select("SELECT * FROM loadtimeslot")
        public List<Pojo> select();
        }
  • 性能:耗時721s,查詢效率相對較低,內存一次性增長過快,很容易撐不住

分頁查詢

  • 查詢接口
    @Mapper
    public interface UserMapper {
        @Select("SELECT * FROM loadtimeslot order by id limit #{offset},#{limit}")
        public List<Pojo> selectByPage(@Param("offset") long offset,@Param("limit") int limit);
    }
    //遞歸查詢
    private void selectData(long offset, List<Pojo> res)
    {
        int limit =100000;
        long start = System.currentTimeMillis();
        List<Pojo> data = oMapper.selectByPage(offset, limit);
        res.addAll(data);
        System.out.print(String.format("Load page data,offset[%d],cost[%d]ms\r\n", offset,System.currentTimeMillis()-start));
        if (data.size()<limit)
            return ;
        else
            selectData(offset+limit, res);
    }
  • 性能:最開始的頁碼查詢速度很快,但是越到最後查詢效率越低,第一頁需要2.4s,最後一頁全量數據需要10.5s,總耗時1452s
	Line 27: Load data from db start 
	Line 38: Load page data,offset[0],cost[2486]ms
	Line 39: Load page data,offset[100000],cost[2048]ms
	Line 40: Load page data,offset[200000],cost[1974]ms
	Line 41: Load page data,offset[300000],cost[2032]ms
	Line 42: Load page data,offset[400000],cost[2048]ms
	Line 43: Load page data,offset[500000],cost[2095]ms
	Line 44: Load page data,offset[600000],cost[2297]ms
	Line 45: Load page data,offset[700000],cost[2407]ms
	Line 46: Load page data,offset[800000],cost[2240]ms
									.
									.
									.
									.
	Line 262: Load page data,offset[22400000],cost[10708]ms
	Line 263: Load page data,offset[22500000],cost[10287]ms
	Line 264: Load page data,offset[22600000],cost[10153]ms
	Line 265: Load page data,offset[22700000],cost[10355]ms
	Line 266: Load page data,offset[22800000],cost[10210]ms
	Line 267: Load page data,offset[22900000],cost[10421]ms
	Line 268: Load page data,offset[23000000],cost[10523]ms
	Line 269: Load page data,offset[23100000],cost[9231]ms
	Line 270: Load end:[1451794]ms
  • 分析原因:limit 1000,100,意思是掃描滿足條件的1000+100 行,丟棄掉前邊的1000行,返回最後的100行,當偏移量足夠大的時候,每次檢索都要執行offset的偏移量處理,性能肯定會越來越差

分頁查詢優化

  • 根據where條件跳過offset的偏移量處理
        @Select("SELECT * FROM loadtimeslot where id>#{offset} order by id asc limit #{limit}")
        public List<Pojo> selectByPage(@Param("offset") long offset,@Param("limit") int limit);
  • 性能: 分頁查詢單次時間消耗不隨offset增大而增多,最後一次10000W條查詢耗時2s,總耗時494s,相比之前的分頁查詢快了將近5倍
	Line 27: Load data from db start 
	Line 38: Load page data,offset[0],cost[4707]ms
	Line 39: Load page data,offset[100000],cost[3254]ms
	Line 40: Load page data,offset[200000],cost[2251]ms
	Line 41: Load page data,offset[300000],cost[2064]ms
	Line 42: Load page data,offset[400000],cost[2034]ms
	Line 43: Load page data,offset[500000],cost[1971]ms
	Line 44: Load page data,offset[600000],cost[2100]ms
	Line 45: Load page data,offset[700000],cost[2146]ms
	Line 46: Load page data,offset[800000],cost[1973]ms
										.
										.
										.
										.
										.
	Line 264: Load page data,offset[22600000],cost[1925]ms
	Line 265: Load page data,offset[22700000],cost[2079]ms
	Line 266: Load page data,offset[22800000],cost[2015]ms
	Line 267: Load page data,offset[22900000],cost[2175]ms
	Line 268: Load page data,offset[23000000],cost[2065]ms
	Line 269: Load page data,offset[23100000],cost[2015]ms
	Line 270: Load page data,offset[23200000],cost[1204]ms
	Line 271: Load end:[494943]ms
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章