如何更快速高效地从数据库查询数据

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 15:44   47   0

背景

一般情况下,我们从数据获读取大量数据,一般通过像这样的sql来查询

select * from xxx a where a.id in (x,x,x)

发现没有,用 in 语句来查询,但是相比于join,in的查询效率要低很多

那如何提高查询效率呢?如何用join来查询,因为一般情况下,我们有id了,怎么跟表关联有关呢?

解决办法

创建临时表,我们可以创建一个tempKey表,专门存放要查询的key。注意一下几点

  1. tempKey表就是临时表,所以每次使用前删掉
  2. 删掉后直接插入要查询的Id到该表中
  3. 然后就可以关联tempkey表查询了

下面,我写个工具类,可以供参考

package com.future.springcloud.common;

import com.future.springcloud.dao.TmpKeyMapper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.function.Function;

@Service
public class MapperUtils {

    @Autowired
    private SqlSessionFactory factory;

    /**
     * 方法说明:batchSelectByKeys
     *
     * @param clasz    dao类
     * @param data     要查询数据的Id
     * @param function 回调
     * @param <U>      参数
     * @param <R>      返回参数
     * @return 返回结果
     * @throws SQLException
     */
    public <U, R> R batchSelectByKeys(Class<U> clasz, List<Integer> data, Function<U, R> function) throws SQLException {
        R result = null;
        SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false);
        Connection conn = sqlSession.getConnection();
        try {
            final boolean autoCommit = conn.getAutoCommit();
            try {
                if (autoCommit) {
                    conn.setAutoCommit(false);
                }
                TmpKeyMapper mapper = sqlSession.getMapper(TmpKeyMapper.class);
                // 查询前先清空tmp_key表
                mapper.clear();
                for (Integer id : data) {
                    // 把key插入到临时表
                    mapper.insert(id);
                }
                U obj = sqlSession.getMapper(clasz);
                // 执行查询操作
                result = function.apply(obj);
                // 提交任务
                conn.commit();
            } catch (Exception e) {
                if (autoCommit) {
                    conn.rollback();
                }
            }
        } catch (SQLException e) {
            String errorMessage = "something error on invoke method batchInsert";
            e.printStackTrace();
            throw new RuntimeException(errorMessage, e);
        } finally {
            conn.close();
            sqlSession.close();
        }
        return result;
    }

}

其中,TmpKeyMapper类代码如下

package com.future.springcloud.dao;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface TmpKeyMapper {

    /**
     *
     * @param id 插入临时表的Key值
     */
    @Insert("insert into tmp_key (id) values (#{id})")
    void insert(@Param("id") Integer id);

    /**
     * 清空临时表
     */
    @Delete("delete from tmp_key")
    void clear();
}

使用

这个工具类怎么使用?不知道的朋友可以看下面的代码

  • dao类
@Mapper
public interface PaymentDao {

    int create(Payment payment);

    Payment getPaymentById(@Param("id") int id);

    @Select(" SELECT * from payment a INNER join tmp_key b on a.id=b.id ")
    Payment getPaymentByIds();

}
  • service实现类
package com.future.springcloud.service.imp;

import com.future.springcloud.common.MapperUtils;
import com.future.springcloud.dao.PaymentDao;
import com.future.springcloud.entities.Payment;
import com.future.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Resource
    private PaymentDao paymentDao;

    @Resource
    private MapperUtils mapperUtils;

    public Payment getPaymentById(int id){
        Payment payment = null;
        try {
            payment = mapperUtils.batchSelectByKeys(PaymentDao.class,Arrays.asList(id),PaymentDao::getPaymentByIds);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return payment;
    }


}

以上方法非常有效,大公司一般都是用这种方法查询数据量大的数据,避免使用in查询。

好久没更新文章了,希望以后能多多分享更多更好的技术,喜欢的可以点赞分享!!

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP