A eficiência da consulta de paginação de dados de um milhão de níveis do SpringBoot aumenta

A eficiência da consulta de paginação personalizada para milhões de dados disparou

1. O motivo da lentidão?

Consulta de paginação de deslocamento + limite, quando a tabela de dados exceder 1 milhão de registros, o desempenho será muito ruim.
O principal motivo é que o método de paginação do limite de deslocamento é consultar desde o início e depois descartar os primeiros registros de deslocamento, portanto, quanto maior o deslocamento do deslocamento, mais lenta será a velocidade da consulta.
O plug-in de paginação do mybatis-plus pode ter esse problema.

2. Como otimizar?

Método 1: reordenação com base no índice, usando MySQL para suportar a operação ORDER, você pode usar o índice para localizar rapidamente algumas tuplas e evitar a varredura completa da tabela
#大于上一页最后一个id
SELECT * FROM table WHERE id>=10000 ORDER BY id ASC LIMIT 0,20
Método 2: use subconsulta/junção + índice para localizar rapidamente a tupla e, em seguida, ler a tupla
SELECT a.* FROM table a JOIN (select id from table limit 100000, 20) b ON a.id = b.id

3. Faça upload do código (método 2 usado por blogueiros)

1. Personalizar página
@Data
public class MyPage<T> implements Serializable {
    
    
    private List<T> records; //结果集
    private Integer total; //符合条件总条数
    private Integer size; //每页记录数
    private Integer current; //当前处于第几页
    private List<T> orders;
    private final boolean optimizeCountSql = true;
    private final boolean hitCount = false;
    private Integer countId;
    private Integer maxLimit;
    private final boolean searchCount = true;
    private Integer pages; // 符合条件总页数
}
2. Classe de implementação ServiceImpl
public MyPage<XXXPageVo> getPageXXX(XXXDto dto) {
    
    
        QueryWrapper<XXX> qw = new QueryWrapper<>();
        qw.lambda() //以下条件是我的业务条件,自行变更自己业务条件
                .eq(ObjectUtils.isNotEmpty(dto.getOrderId()),XXX::getOrderId,dto.getOrderId())
                .eq(ObjectUtils.isNotEmpty(dto.getOrderNo()) && dto.getOrderNo().length() == 14,XXX::getNewSysOrderNo,dto.getOrderNo())
                .eq(ObjectUtils.isNotEmpty(dto.getOrderNo()) && dto.getOrderNo().length() > 14,XXX::getOrderNo,dto.getOrderNo())
                .eq(ObjectUtils.isNotEmpty(dto.getMainDriverId()),XXX::getMainDriverId,dto.getMainDriverId())
                .like(ObjectUtils.isNotEmpty(dto.getMainDriverName()),XXX::getMainDriverName,dto.getMainDriverName())
                .like(ObjectUtils.isNotEmpty(dto.getMainDriverVehicleNo()),XXX::getMainDriverVehicleNo,dto.getMainDriverVehicleNo())
                .eq(ObjectUtils.isNotEmpty(dto.getKmDriverId()),XXX::getKmDriverId,dto.getKmDriverId())
                .like(ObjectUtils.isNotEmpty(dto.getKmDriverName()),XXX::getKmDriverName,dto.getKmDriverName())
                .like(ObjectUtils.isNotEmpty(dto.getKmDriverVehicleNo()),XXX::getKmDriverVehicleNo,dto.getKmDriverVehicleNo())
                .eq(ObjectUtils.isNotEmpty(dto.getLineGroupId()),XXX::getLineGroupId,dto.getLineGroupId())
                .eq(ObjectUtils.isNotEmpty(dto.getTotalLineGroupId()),XXX::getTotalLineGroupId,dto.getTotalLineGroupId())
                .eq(ObjectUtils.isNotEmpty(dto.getPassengerMobile()),XXX::getPassengerMobile,dto.getPassengerMobile())
                .eq(ObjectUtils.isNotEmpty(dto.getKmDriverScore()),XXX::getKmDriverScore,dto.getKmDriverScore())
                .eq(ObjectUtils.isNotEmpty(dto.getZtDriverScore()),XXX::getZtDriverScore,dto.getZtDriverScore())
                .eq(ObjectUtils.isNotEmpty(dto.getUid()),XXX::getUid,dto.getUid())
                .eq(ObjectUtils.isNotEmpty(dto.getStatus()),XXX::getStatus,dto.getStatus());
        if(ObjectUtils.isNotEmpty(dto.getStartArrangeRunTime()) && ObjectUtils.isNotEmpty(dto.getEndArrangeRunTime())){
    
    
            long sl = dto.getStartArrangeRunTime().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()/1000;
            long el = dto.getEndArrangeRunTime().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()/1000;
            qw.lambda().between(XXX::getArrangeRunTime,sl,el);
        }
        if(ObjectUtils.isNotEmpty(dto.getStartUpdateTime()) && ObjectUtils.isNotEmpty(dto.getEndUpdateTime())){
    
    
            long slu = dto.getStartUpdateTime().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()/1000;
            long elu = dto.getEndUpdateTime().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()/1000;
            qw.lambda().between(XXX::getUpdateTime,slu,elu);
        }
        // CurrentSize 自定义字段 例如: 现在分页处于第3页,每页条数是10条,那么第四页需要从
        // 第31条开始查询,抛弃前面30条数据,也就有了下面的这行代码 
        dto.setCurrentSize(dto.getCurrent() * dto.getSize() - dto.getSize());
        Integer total = baseMapper.selectCount(qw); // 关键点(查询出符合条件的总条数)
        List<XXXPageVo> resList = baseMapper.pageComments(dto);
        //以下是自定义Page拼装
        MyPage<XXXPageVo> page = new MyPage<>();
        int pages = (int) Math.ceil((double) total / dto.getSize());
        page.setTotal(total);
        page.setPages(pages);
        page.setRecords(resList);
        page.setSize(dto.getSize());
        page.setCurrent(dto.getCurrent());
        return page;
    }

3.Mapper.xml

<select id="pageComments" parameterType="包名.XXXDTO" resultType="包名.XXXPageVO">
        SELECT
        a.id,
        uniacid,
        order_no,
        order_id,
        total_line_group_id,
        total_line_group_name,
        line_group_id,
        zt_driver_label_ids,
        zt_driver_score,
        zt_driver_other_comment,
        zt_driver_label_str,
        main_driver_vehicle_no,
        km_driver_label_ids,
        km_driver_score,
        km_driver_label_str,
        description,
        main_driver_id,
        km_driver_other_comment,
        main_driver_name,
        km_driver_id,
        km_driver_name,
        km_driver_vehicle_no,
        other_comment_content,
        order_name,
        from_unixtime( arrange_run_time, '%Y-%m-%d %H:%i:%s' ) AS arrange_run_time,
        passenger_name,
        passenger_mobile,
        uid,
        wx_name,
        new_sys_order_no,
        recovery_time,
        from_unixtime( update_time, '%Y-%m-%d %H:%i:%s' ) AS update_time,
        update_user_id,
        update_user_name,
        is_del,
        STATUS,
        from_type
        FROM
        table a
        INNER JOIN
        (
        SELECT
        id
        FROM
        table
        where
        is_del = 0
        <if test="XXXDTO.orderId != null and XXXDTO.orderId != '' ">
            AND order_id = #{XXXDTO.orderId}
        </if>
        <if test="XXXDTO.orderNo != null and XXXDTO.orderNo != '' and XXXDTO.orderNo.length == 14 ">
            AND new_sys_order_no = #{XXXDTO.orderNo}
        </if>
        <if test="XXXDTO.orderNo != null and XXXDTO.orderNo != '' and XXXDTO.orderNo.length &gt; 14 ">
            AND order_no = #{XXXDTO.orderNo}
        </if>
        <if test="XXXDTO.mainDriverId != null and XXXDTO.mainDriverId != '' ">
            AND main_driver_id = #{XXXDTO.mainDriverId}
        </if>
        <if test="XXXDTO.mainDriverName != null and XXXDTO.mainDriverName != '' ">
            AND main_driver_name like CONCAT('%',CONCAT(#{XXXDTO.mainDriverName},'%'))
        </if>
        <if test="XXXDTO.mainDriverVehicleNo != null and XXXDTO.mainDriverVehicleNo != '' ">
            AND main_driver_vehicle_no like CONCAT('%',CONCAT(#{XXXDTO.mainDriverVehicleNo},'%'))
        </if>
        <if test="XXXDTO.kmDriverId != null and XXXDTO.kmDriverId != '' ">
            AND km_driver_id = #{XXXDTO.kmDriverId}
        </if>
        <if test="XXXDTO.kmDriverName != null and XXXDTO.kmDriverName != '' ">
            AND km_driver_name like CONCAT('%',CONCAT(#{XXXDTO.kmDriverName},'%'))
        </if>
        <if test="XXXDTO.kmDriverVehicleNo != null and XXXDTO.kmDriverVehicleNo != '' ">
            AND km_driver_vehicle_no like CONCAT('%',CONCAT(#{XXXDTO.kmDriverVehicleNo},'%'))
        </if>
        <if test="XXXDTO.lineGroupId != null and XXXDTO.lineGroupId != '' ">
            AND line_group_id = #{XXXDTO.lineGroupId}
        </if>
        <if test="XXXDTO.totalLineGroupId != null and XXXDTO.totalLineGroupId != '' ">
            AND total_line_group_id = #{XXXDTO.totalLineGroupId}
        </if>
        <if test="XXXDTO.passengerMobile != null and XXXDTO.passengerMobile != '' ">
            AND passenger_mobile = #{XXXDTO.passengerMobile}
        </if>
        <if test="XXXDTO.kmDriverScore != null and XXXDTO.kmDriverScore != '' ">
            AND km_driver_score = #{XXXDTO.kmDriverScore}
        </if>
        <if test="XXXDTO.ztDriverScore != null and XXXDTO.ztDriverScore != '' ">
            AND zt_driver_score = #{XXXDTO.ztDriverScore}
        </if>
        <if test="XXXDTO.uid != null and XXXDTO.uid != '' ">
            AND uid = #{XXXDTO.uid}
        </if>
        <if test="XXXDTO.status != null and XXXDTO.status != '' ">
            AND status = #{XXXDTO.status}
        </if>
        <if test="XXXDTO.startArrangeRunTime != null and XXXDTO.endArrangeRunTime != null ">
            AND arrange_run_time BETWEEN unix_timestamp(#{XXXDTO.startArrangeRunTime}) AND unix_timestamp(#{XXXDTO.endArrangeRunTime})
        </if>
        <if test="XXXDTO.startUpdateTime != null and XXXDTO.endUpdateTime != null">
            AND update_time BETWEEN unix_timestamp(#{XXXDTO.startUpdateTime}) AND unix_timestamp(#{XXXDTO.endUpdateTime})
        </if>
        ORDER BY update_time DESC
        LIMIT #{XXXDTO.currentSize},
        #{XXXDTO.size}
        ) b on a.id = b.id
    </select>

Em relação às renderizações, não farei capturas de tela. A maioria dos blogs provavelmente usa esses dois métodos. O blogueiro apenas integrou a lógica para evitar armadilhas e a usou para projetos on-line. A eficiência foi realmente melhorada dezenas de vezes. Será mais rápido se adicionamos assistência ao índice do banco de dados.

Acho que você gosta

Origin blog.csdn.net/hsadfdsahfdsgfds/article/details/127474046
Recomendado
Clasificación