---
url: /notes/面试/真实面经/信华信技术/index.md
---
## get、post请求区别

[HTTP 中 GET 和 POST 的区别是什么？ - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/question/1853639415351156737)

|          | get                             | post                                                         |
| -------- | ------------------------------- | ------------------------------------------------------------ |
| 定义     | 获取资源                        | 提交数据                                                     |
| 请求参数 | 拼接在url上，长度限制在2046字节 | 在请求体中，长度理论无限制，取决于服务器配置，如nginx默认1MB |
| 缓存     | 被浏览器和CDN缓存               | 一般不缓存                                                   |

## 队列、堆栈区别

队列：先进先出
堆栈：先进后出

## 数据量大的处理经验

### sql优化

查看执行计划，合理使用索引，联合索引，满足最左匹配原则

join 小表驱动大表

[为什么在 MySQL 中不推荐使用多表 JOIN？ - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/question/1780933295568089090)

尽量不使用左like

尽量避免select \*

尽量不使用函数，比如日期类的查询

in换成exists，in适合小表驱动大表，exist适合大表驱动小表

### 数据放在内存处理

需要计算的函数可以放在代码中处理

### 多线程处理

多线程并行查询

### 网络传输数据大小过大

尝试压缩数据，如gzip

## 项目亮点

### 针对单个方法级别的callback

可配置的callback

注册的bean信息，是否异步，是否忽略错误，前、后置执行

通过是否抛出异常可实现忽略错误

### 自定义线程+队列+kafka，websocket监控图形

同一个topic存储一条生产线的所有点位信息，单个点位的信息通过Map\<String,Queue>存储，数据根据时间排序

各自点位的消费者线程通过点位id读取各自的数据

每个点位的图形通过图形id确认，通过websocket传输到前端

### 接口日志

通过模板方法设计模式，存储接收和发送报文，可重放接口

可通过统一前缀，走同一个方法记录日志

可通过aop拦截，拦截@RequestMapping 及其变体注解的方法

## 项目遇到的难题

一个报表统计的业务，每个月底执行一次，从数据湖获取数据，一个点位几十万，多个点位上百万条数据，在内存中处理，计算平均值，最大值，最小值；

定时器晚上执行，执行2个多小时

数据库查询数据快

sql查询映射到实体字段慢

内存计算慢

分批多线程提前处理计算，数据存储中间表

每个点位并行处理

实体映射，尽量少字段，构造器映射

**构造器映射**

```java
// 构造器映射
@Data
public class PointData {
    private final String pointId;    // 使用final
    private final double value;
    private final long timestamp;
    
    // 构造器映射
    public PointData(ResultSet rs) throws SQLException {
        this.pointId = rs.getString("point_id");
        this.value = rs.getDouble("value");
        this.timestamp = rs.getTimestamp("collect_time").getTime();
    }
}

// MyBatis 使用构造器
<constructor>
    <idArg column="point_id" javaType="String"/>
    <arg column="value" javaType="double"/>
    <arg column="collect_time" javaType="long"/>
</constructor>
```

**MyBatis 优化方案**

```java
// 1. 使用@Constructor注解
@Data
public class PointData {
    private final String pointId;
    private final double value;
    private final long timestamp;
    
    @Constructor
    public PointData(
        @Param("point_id") String pointId,
        @Param("value") double value,
        @Param("collect_time") long timestamp) {
        this.pointId = pointId;
        this.value = value;
        this.timestamp = timestamp;
    }
}

// 2. 使用ResultHandler优化大量数据处理
@Mapper
public interface PointDataMapper {
    void selectLargeData(@Param("startTime") Date startTime,
                        @Param("endTime") Date endTime,
                        ResultHandler<PointData> handler);
}
```
