¿Cómo diseñar la solución de importación y exportación para millones de datos?

  • prospecto

  • 1 Comparación de ventajas y desventajas de las versiones tradicionales de POI

  • 2 La forma de usar depende de la situación

  • 3 millones de datos de importación y exportación (plato)

  • 4 Resumen


prospecto

En el desarrollo de proyectos, a menudo es necesario utilizar la importación y exportación de datos. Importar es importar de Excel a la base de datos, y exportar es consultar datos de la base de datos y luego usar POI para escribir en Excel.

El trasfondo de escribir este artículo es porque me encontré con la importación y exportación de big data en el trabajo. Dado que el problema ha surgido, ¡es mejor huir y matarlo! ! !

Siempre que se resuelva esta vez, será fácil resolver el mismo problema más adelante.

Sin más preámbulos, ¡comencemos a masturbarnos! ! !

1 Comparación de ventajas y desventajas de las versiones tradicionales de POI

De hecho, cuando se piensa en importar y exportar datos, es natural pensar en la tecnología poi de apache y en los problemas de la versión de Excel.

¡Ya que necesitamos importar y exportar, echemos un vistazo a la versión de la tecnología tradicional de poi y comparemos sus ventajas y desventajas primero!

En primer lugar, sabemos que la interfaz con la que estamos más familiarizados en POI es una interfaz como WorkBook. Nuestra versión de POI también se actualiza y las clases de implementación de estos puertos se actualizan al mismo tiempo:

  • HSSFLibro de trabajo:

Esta clase de implementación es el objeto que más usamos en los primeros días y puede operar todas las versiones de Excel anteriores a Excel2003 (incluida la 2003). Antes de 2003, el sufijo de versión de Excel todavía era .xls

  • Libro de trabajo XSSF:

Esta clase de implementación se puede encontrar en muchas empresas y todavía está en uso. Es la versión entre Excel2003--Excel2007. La extensión de Excel es .xlsx

  • Libro de trabajo SXSSF:

Esta clase de implementación solo está disponible en versiones posteriores a POI3.8, puede operar todas las versiones de Excel posteriores a Excel2007 y la extensión es .xlsx

Después de conocer a grandes rasgos que usaremos estas tres clases de implementación y las versiones y sufijos de Excel que pueden operar al momento de importar y exportar operaciones, las analizaremos desde sus ventajas y desventajas.

HSSFLibro de trabajo

Sin embargo, es la forma más común en la versión de PDI:

  • Su desventaja es que solo puede exportar hasta 65535 filas, es decir, la función de datos exportados reportará un error si excede estos datos;

  • Su ventaja es que no informará sobre el desbordamiento de memoria. (Debido a que la cantidad de datos es inferior a 7w, la memoria generalmente es suficiente. En primer lugar, debe saber claramente que este método es leer los datos en la memoria primero y luego operarlos)

XSSFLibro de trabajo

  • Ventajas: La apariencia de este formulario es para romper HSSFWorkbookla limitación de 65535 líneas, para las 1,048,576 líneas y 16,384 columnas de la versión Excel2007, y puede exportar hasta 104w de datos;

  • Desventajas: Llegó el problema que lo acompañaba.Aunque el número de filas de datos exportados ha aumentado muchas veces, el problema de desbordamiento de memoria subsiguiente también se ha convertido en una pesadilla. Debido a que el libro, la hoja, la fila, la celda, etc. que creó se almacenan en la memoria antes de escribirse en Excel (sin contar algunos estilos y formatos de Excel, etc.), es concebible que si la memoria no se desborda , el ¡Es un poco acientífico! ! !

SXSSFLibro de trabajo

A partir de la versión 3.8 de POI, se proporciona un método SXSSF con poca memoria ocupada basado en XSSF:

ventaja:

  • Este método generalmente no causará un desbordamiento de la memoria (utiliza el disco duro a cambio de espacio en la memoria,

  • Es decir, cuando los datos en la memoria alcancen un cierto nivel, los datos se conservarán en el disco duro para su almacenamiento, y todos los datos almacenados en la memoria serán los datos más recientes).

  • Y admite la creación de grandes archivos de Excel (más de un millón de datos son más que suficientes).

defecto:

  • Dado que parte de los datos se conservan en el disco duro y no se pueden ver ni acceder, conducirá a,

  • En el mismo momento solo podemos acceder a una cierta cantidad de datos, es decir, los datos almacenados en la memoria;

  • sheet.clone()El método ya no será compatible, o debido a la persistencia;

  • Ya no se admite la evaluación de fórmulas o, debido a la persistencia, los datos del disco duro no se pueden leer en la memoria para el cálculo;

  • Cuando se utiliza el método de plantilla para descargar datos, el encabezado de la tabla no se puede cambiar o, debido al problema de persistencia, no se puede cambiar después de escribir en el disco duro;

2 La forma de usar depende de la situación

Después de comprender y conocer las ventajas y desventajas de estos tres libros de trabajo, el método a utilizar depende de la situación:

Generalmente tomo decisiones de análisis basadas en las siguientes situaciones:

1. Cuando los datos que importamos y exportamos a menudo no superan los 7w, se pueden usar  HSSFWorkbook o  XSSFWorkbookambos;

2. Se recomienda usar cuando la cantidad de datos exceda 7w y el Excel exportado no involucre operaciones en estilos, fórmulas y formatos de Excel SXSSFWorkbook;

3. Cuando la cantidad de datos excede 7w, y necesitamos operar los encabezados de tabla, estilos, fórmulas, etc. en Excel, en este momento, podemos usar el  XSSFWorkbook método de cooperación para consultar en lotes y escribir en Excel en lotes;

3 millones de datos de importación y exportación (plato)

He hecho muchos presagios, así que ahora hablaré sobre las soluciones de importación y exportación de más de un millón de datos que encontré en mi trabajo:

Para resolver un problema, primero debemos entender cuál es el problema.

1. La cantidad de datos que encontré es enorme, y usar el método POI tradicional para completar la importación y exportación obviamente causará un desbordamiento de memoria y la eficiencia será muy baja;

2. select * from tableNameDefinitivamente no es posible usar una gran cantidad de datos directamente, y definitivamente será muy lento encontrar 3 millones de datos a la vez;

3. Cuando los datos de 300w se exportan a Excel, no deben escribirse en una hoja, por lo que la eficiencia será muy baja, se estima que tardará unos minutos en abrirse;

4. Los datos de 300w exportados a Excel no deben exportarse a Excel línea por línea. Las operaciones de E/S frecuentes son absolutamente inaceptables;

5. Al importar, se almacenan 3 millones de datos en la base de datos, y definitivamente no funcionará si los inserta uno por uno en un bucle;

6. Al importar datos de 300w, si usa la inserción por lotes de Mybatis, definitivamente no funcionará, porque la inserción por lotes de Mybatis es en realidad un ciclo SQL, también es muy lento.

Soluciones:

Para 1:

De hecho, el problema es el desbordamiento de la memoria. Solo necesitamos usar el método POI presentado anteriormente. El problema principal es que el POI original es bastante complicado de resolver.

Después de consultar la información, encontré una herramienta de empaquetado de puntos de interés EasyExcel de Ali, y los problemas anteriores se resolverán;

Para 2:

No podemos consultar todos los datos a la vez, podemos consultar en lotes, pero es solo cuestión de consultar varias veces, y hay muchos complementos de paginación en el mercado. Este problema es fácil de resolver.

Para 3:

Puede escribir 3 millones de datos en diferentes hojas, y solo se puede escribir un millón de datos en cada hoja.

Para 4:

No es posible escribir en Excel línea por línea, podemos escribir los datos consultados en lotes en Excel en lotes.

Para 5:

Al importar a la base de datos, podemos almacenar los datos leídos en Excel en una colección y, cuando alcanza cierta cantidad, insertarlos directamente en la base de datos en lotes.

Para 6:

No podemos usar la inserción por lotes de Mybatis, podemos usar la inserción por lotes de JDBC y cooperar con las transacciones para completar la inserción por lotes en la base de datos. Es decir, Excel lee en lotes + inserciones de JDBC en lotes + transacciones.

3.1 Introducción a EasyExcel

Adjunte la dirección de GitHub: https://github.com/alibaba/easyexcel

Los tutoriales e instrucciones en la dirección de GitHub son muy detallados y hay códigos de demostración para leer y escribir, por lo que no entraré en detalles sobre su introducción aquí.

En cuanto a cómo la capa inferior de EasyExcel se da cuenta de esto, queda por estudiar.

Exportación de datos 3.2 300w

EasyExcel completa la exportación de datos de 300w. La dificultad técnica ya se conoce, y el siguiente paso es proporcionar su propia solución a esta dificultad.

Soluciones de exportación de datos de 300w:

  • En primer lugar, en el nivel de la base de datos de consulta, debe consultar en lotes (uso 20w por consulta)

  • Use la herramienta EasyExcel para escribir los datos una vez cada vez que finaliza la consulta;

  • Cuando una Hoja se llene con 100w de datos, comience a escribir los datos consultados en otra Hoja;

  • Esto se repite hasta que todos los datos se exportan a Excel.

Aviso:

1. Necesitamos calcular el número de hojas y el número de escrituras en bucle. Especialmente los tiempos de escritura de la última hoja.

Debido a que no sabe cuántos datos se escriben en la última selección de Hoja, puede ser 100w o 25w, porque los 300w aquí son solo datos simulados, y los datos exportados pueden ser más o menos de 300w

2. Necesitamos contar la cantidad de escrituras, porque usamos consultas de paginación, por lo que debemos prestar atención a la cantidad de escrituras.

De hecho, cuántas veces consulta la base de datos es cuántas veces escribe

//导出逻辑代码
public void dataExport300w(HttpServletResponse response) {
    {
        OutputStream outputStream = null;
        try {
            long startTime = System.currentTimeMillis();
            System.out.println("导出开始时间:" + startTime);

            outputStream = response.getOutputStream();
            ExcelWriter writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX);
            String fileName = new String(("excel100w").getBytes(), "UTF-8");

            //title
            Table table = new Table(1);
            List<List<String>> titles = new ArrayList<List<String>>();
            titles.add(Arrays.asList("onlineseqid"));
            titles.add(Arrays.asList("businessid"));
            titles.add(Arrays.asList("becifno"));
            titles.add(Arrays.asList("ivisresult"));
            titles.add(Arrays.asList("createdby"));
            titles.add(Arrays.asList("createddate"));
            titles.add(Arrays.asList("updateby"));
            titles.add(Arrays.asList("updateddate"));
            titles.add(Arrays.asList("risklevel"));
            table.setHead(titles);

            //模拟统计查询的数据数量这里模拟100w
            int count = 3000001;
            //记录总数:实际中需要根据查询条件进行统计即可
            Integer totalCount = actResultLogMapper.findActResultLogByCondations(count);
            //每一个Sheet存放100w条数据
            Integer sheetDataRows = ExcelConstants.PER_SHEET_ROW_COUNT;
            //每次写入的数据量20w
            Integer writeDataRows = ExcelConstants.PER_WRITE_ROW_COUNT;
            //计算需要的Sheet数量
            Integer sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);
            //计算一般情况下每一个Sheet需要写入的次数(一般情况不包含最后一个sheet,因为最后一个sheet不确定会写入多少条数据)
            Integer oneSheetWriteCount = sheetDataRows / writeDataRows;
            //计算最后一个sheet需要写入的次数
            Integer lastSheetWriteCount = totalCount % sheetDataRows == 0 ? oneSheetWriteCount : (totalCount % sheetDataRows % writeDataRows == 0 ? (totalCount / sheetDataRows / writeDataRows) : (totalCount / sheetDataRows / writeDataRows + 1));

            //开始分批查询分次写入
            //注意这次的循环就需要进行嵌套循环了,外层循环是Sheet数目,内层循环是写入次数
            List<List<String>> dataList = new ArrayList<>();
            for (int i = 0; i < sheetNum; i++) {
                //创建Sheet
                Sheet sheet = new Sheet(i, 0);
                sheet.setSheetName("测试Sheet1" + i);
                //循环写入次数: j的自增条件是当不是最后一个Sheet的时候写入次数为正常的每个Sheet写入的次数,如果是最后一个就需要使用计算的次数lastSheetWriteCount
                for (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {
                    //集合复用,便于GC清理
                    dataList.clear();
                    //分页查询一次20w
                    PageHelper.startPage(j + 1 + oneSheetWriteCount * i, writeDataRows);
                    List<ActResultLog> reslultList = actResultLogMapper.findByPage100w();
                    if (!CollectionUtils.isEmpty(reslultList)) {
                        reslultList.forEach(item -> {
                            dataList.add(Arrays.asList(item.getOnlineseqid(), item.getBusinessid(), item.getBecifno(), item.getIvisresult(), item.getCreatedby(), Calendar.getInstance().getTime().toString(), item.getUpdateby(), Calendar.getInstance().getTime().toString(), item.getRisklevel()));
                        });
                    }
                    //写数据
                    writer.write0(dataList, sheet, table);
                }
            }

            // 下载EXCEL
            response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1") + ".xlsx");
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");
            writer.finish();
            outputStream.flush();
            //导出时间结束
            long endTime = System.currentTimeMillis();
            System.out.println("导出结束时间:" + endTime + "ms");
            System.out.println("导出所用时间:" + (endTime - startTime) / 1000 + "秒");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.2.1 Estado de la máquina de prueba

La siguiente es la configuración de la máquina de prueba

3.2.2 Uso de la versión de la base de datos

La base de datos que uso es Oracle19C, de hecho, cuando la cantidad de datos no supera los 100 millones, el rendimiento de Mysql y Oracle no es muy diferente, si supera los 100 millones, las ventajas de Oracle en todos los aspectos serán obvias.

Por lo tanto, el impacto de usar la base de datos a tiempo puede ignorarse aquí, y la prueba puede completarse usando mysql sin instalar Oracle por separado.

En esta prueba, en términos de consulta, utilicé la consulta simulada de 3 millones de datos por número de fila. Este tipo de consulta no es muy eficiente. De hecho, todavía hay mucho espacio para la optimización para acelerar la consulta.

Por ejemplo: consulte claramente campos específicos, no use asteriscos, consulte campos con frecuencia y agregue índices para mejorar la eficiencia de las consultas tanto como sea posible, y el tiempo puede ser más corto.

<select id="findByPage300w" resultType="show.mrkay.pojo.ActResultLog">
    select *
    from ACT_RESULT_LOG
    where rownum <![CDATA[<]]> 3000001
</select>
-- 建表语句:可以参考一下
-- Create table
create table ACT_RESULT_LOG
(
  onlineseqid VARCHAR2(32),
  businessid  VARCHAR2(32),
  becifno     VARCHAR2(32),
  ivisresult  VARCHAR2(32),
  createdby   VARCHAR2(32),
  createddate DATE,
  updateby    VARCHAR2(32),
  updateddate DATE,
  risklevel   VARCHAR2(32)
)
tablespace STUDY_KAY
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );

3.2.3 Resultados de la prueba

El siguiente es el tiempo que tardan los datos de 300w en exportarse de DB a Excel

De los resultados anteriores, se puede ver que el tiempo de exportación de datos de 300w toma 2 minutos y 15 segundos, y esto es cuando la entidad no se usa como mapeo.Si el mapeo de entidad no es aplicable a la encapsulación de bucle, la velocidad será más rápido (por supuesto, esto también es en ausencia de Al configurar otros estilos de tabla, como encabezados de tabla)

En general, la velocidad no es mala.

Después de verificar mucha información en Internet, un bloguero probó que se necesitaron 105 segundos para exportar datos de 102 W usando EasyExcel. Para obtener más detalles, consulte el enlace:

https://blog.csdn.net/u014299266/article/details/107790561

Mire el efecto de exportación: el archivo sigue siendo bastante grande con 163M

3.2.4 Resumen de exportación

Después de la prueba, EasyExcel sigue siendo muy rápido y es bastante conveniente de usar. El autor también proporciona un método especial para cerrar la transmisión, que no requiere que cerremos manualmente la transmisión y también evita una serie de problemas causados ​​por nosotros. a menudo se olvida de cerrar la corriente.

Este es el final de la prueba de exportación. Los datos con un volumen de datos inferior a 300 W se pueden exportar en una hoja. No se demostrará aquí.

3.3 Importación de datos de 300w

El código no es importante, la idea es lo primero.

Soluciones de importación de datos de 300 W

1. El primer paso es leer los datos de 300w en Excel en lotes. EasyExcel tiene su propia solución para esto. Podemos referirnos a la Demo. Solo necesitamos aumentar el parámetro 3000 en lotes. Uso 20w; (puedes entender el código después de un tiempo)

2. El segundo es insertar en la base de datos. Cómo insertar estos 200.000 datos, por supuesto, no puede repetir uno por uno. Debe insertar estos 200.000 datos en lotes. Además, no puede usar el lenguaje de inserción por lotes de Mybatis, porque la eficiencia también es baja. Puede consultar el siguiente enlace [Comparación de rendimiento entre la inserción por lotes de Myabtis y la inserción por lotes de JDBC]

3. Utilice la operación por lotes de la transacción JDBC+ para insertar datos en la base de datos. (Lectura por lotes + inserción por lotes de JDBC + control manual de transacciones)

https://www.cnblogs.com/wxw7blog/p/8706797.html

3.3.1 Datos de la base de datos (antes de la importación)

como se muestra en la imagen

3.3.2 Código comercial central

// EasyExcel的读取Excel数据的API
@Test
public void import2DBFromExcel10wTest() {
    String fileName = "D:\\StudyWorkspace\\JavaWorkspace\\java_project_workspace\\idea_projects\\SpringBootProjects\\easyexcel\\exportFile\\excel300w.xlsx";
    //记录开始读取Excel时间,也是导入程序开始时间
    long startReadTime = System.currentTimeMillis();
    System.out.println("------开始读取Excel的Sheet时间(包括导入数据过程):" + startReadTime + "ms------");
    //读取所有Sheet的数据.每次读完一个Sheet就会调用这个方法
    EasyExcel.read(fileName, new EasyExceGeneralDatalListener(actResultLogService2)).doReadAll();
    long endReadTime = System.currentTimeMillis();
    System.out.println("------结束读取Excel的Sheet时间(包括导入数据过程):" + endReadTime + "ms------");
}
// 事件监听
public class EasyExceGeneralDatalListener extends AnalysisEventListener<Map<Integer, String>> {
    /**
     * 处理业务逻辑的Service,也可以是Mapper
     */
    private ActResultLogService2 actResultLogService2;

    /**
     * 用于存储读取的数据
     */
    private List<Map<Integer, String>> dataList = new ArrayList<Map<Integer, String>>();

    public EasyExceGeneralDatalListener() {
    }
    
    public EasyExceGeneralDatalListener(ActResultLogService2 actResultLogService2) {
        this.actResultLogService2 = actResultLogService2;
    }
    
    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        //数据add进入集合
        dataList.add(data);
        //size是否为100000条:这里其实就是分批.当数据等于10w的时候执行一次插入
        if (dataList.size() >= ExcelConstants.GENERAL_ONCE_SAVE_TO_DB_ROWS) {
            //存入数据库:数据小于1w条使用Mybatis的批量插入即可;
            saveData();
            //清理集合便于GC回收
            dataList.clear();
        }
    }

    /**
     * 保存数据到DB
     *
     * @param
     * @MethodName: saveData
     * @return: void
     */
    private void saveData() {
        actResultLogService2.import2DBFromExcel10w(dataList);
        dataList.clear();
    }
    
    /**
     * Excel中所有数据解析完毕会调用此方法
     *
     * @param: context
     * @MethodName: doAfterAllAnalysed
     * @return: void
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
        dataList.clear();
    }
}
//JDBC工具类
public class JDBCDruidUtils {
    private static DataSource dataSource;

    /*
   创建数据Properties集合对象加载加载配置文件
    */
    static {
        Properties pro = new Properties();
        //加载数据库连接池对象
        try {
            //获取数据库连接池对象
            pro.load(JDBCDruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(pro);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
    获取连接
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }


    /**
     * 关闭conn,和 statement独对象资源
     *
     * @param connection
     * @param statement
     * @MethodName: close
     * @return: void
     */
    public static void close(Connection connection, Statement statement) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭 conn , statement 和resultset三个对象资源
     *
     * @param connection
     * @param statement
     * @param resultSet
     * @MethodName: close
     * @return: void
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        close(connection, statement);
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /*
    获取连接池对象
     */
    public static DataSource getDataSource() {
        return dataSource;
    }

}
# druid.properties配置
driverClassName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:ORCL
username=mrkay
password=******
initialSize=10
maxActive=50
maxWait=60000
// Service中具体业务逻辑

/**
 * 测试用Excel导入超过10w条数据,经过测试发现,使用Mybatis的批量插入速度非常慢,所以这里可以使用 数据分批+JDBC分批插入+事务来继续插入速度会非常快
 *
 * @param
 * @MethodName: import2DBFromExcel10w
 * @return: java.util.Map<java.lang.String, java.lang.Object>
 */
@Override
public Map<String, Object> import2DBFromExcel10w(List<Map<Integer, String>> dataList) {
    HashMap<String, Object> result = new HashMap<>();
    //结果集中数据为0时,结束方法.进行下一次调用
    if (dataList.size() == 0) {
        result.put("empty", "0000");
        return result;
    }
    //JDBC分批插入+事务操作完成对10w数据的插入
    Connection conn = null;
    PreparedStatement ps = null;
    try {
        long startTime = System.currentTimeMillis();
        System.out.println(dataList.size() + "条,开始导入到数据库时间:" + startTime + "ms");
        conn = JDBCDruidUtils.getConnection();
        //控制事务:默认不提交
        conn.setAutoCommit(false);
        String sql = "insert into ACT_RESULT_LOG (onlineseqid,businessid,becifno,ivisresult,createdby,createddate,updateby,updateddate,risklevel) values";
        sql += "(?,?,?,?,?,?,?,?,?)";
        ps = conn.prepareStatement(sql);
        //循环结果集:这里循环不支持"烂布袋"表达式
        for (int i = 0; i < dataList.size(); i++) {
            Map<Integer, String> item = dataList.get(i);
            ps.setString(1, item.get(0));
            ps.setString(2, item.get(1));
            ps.setString(3, item.get(2));
            ps.setString(4, item.get(3));
            ps.setString(5, item.get(4));
            ps.setTimestamp(6, new Timestamp(System.currentTimeMillis()));
            ps.setString(7, item.get(6));
            ps.setTimestamp(8, new Timestamp(System.currentTimeMillis()));
            ps.setString(9, item.get(8));
            //将一组参数添加到此 PreparedStatement 对象的批处理命令中。
            ps.addBatch();
        }
        //执行批处理
        ps.executeBatch();
        //手动提交事务
        conn.commit();
        long endTime = System.currentTimeMillis();
        System.out.println(dataList.size() + "条,结束导入到数据库时间:" + endTime + "ms");
        System.out.println(dataList.size() + "条,导入用时:" + (endTime - startTime) + "ms");
        result.put("success", "1111");
    } catch (Exception e) {
        result.put("exception", "0000");
        e.printStackTrace();
    } finally {
        //关连接
        JDBCDruidUtils.close(conn, ps);
    }
    return result;
}

3.3.3 Resultados de la prueba

El siguiente es el tiempo para leer y escribir datos de 300w:

Aproximadamente calcular:

El tiempo total desde el inicio de la lectura hasta la importación del lote intermedio hasta el final del programa:  (1623127964725-1623127873630)/1000=91.095segundos

Los datos de 300w se insertan exactamente 15 veces y el tiempo completo: 8209 milisegundos o 8,209 segundos

El tiempo calculado para leer datos de 300w es: 91.095-8.209=82.886segundos

El resultado es obvio:

EasyExcel solo tardó 82,886 segundos en leer datos de 300 W en lotes

El uso de la operación por lotes + transacción de JDBC para insertar piezas de 300w de síntesis de datos toma solo 8.209 segundos

------开始读取Excel的Sheet时间(包括导入数据过程):1623127873630ms------
200000条,开始导入到数据库时间:1623127880632ms
200000条,结束导入到数据库时间:1623127881513ms
200000条,导入用时:881ms
200000条,开始导入到数据库时间:1623127886945ms
200000条,结束导入到数据库时间:1623127887429ms
200000条,导入用时:484ms
200000条,开始导入到数据库时间:1623127892894ms
200000条,结束导入到数据库时间:1623127893397ms
200000条,导入用时:503ms
200000条,开始导入到数据库时间:1623127898607ms
200000条,结束导入到数据库时间:1623127899066ms
200000条,导入用时:459ms
200000条,开始导入到数据库时间:1623127904379ms
200000条,结束导入到数据库时间:1623127904855ms
200000条,导入用时:476ms
200000条,开始导入到数据库时间:1623127910495ms
200000条,结束导入到数据库时间:1623127910939ms
200000条,导入用时:444ms
200000条,开始导入到数据库时间:1623127916271ms
200000条,结束导入到数据库时间:1623127916744ms
200000条,导入用时:473ms
200000条,开始导入到数据库时间:1623127922465ms
200000条,结束导入到数据库时间:1623127922947ms
200000条,导入用时:482ms
200000条,开始导入到数据库时间:1623127928260ms
200000条,结束导入到数据库时间:1623127928727ms
200000条,导入用时:467ms
200000条,开始导入到数据库时间:1623127934374ms
200000条,结束导入到数据库时间:1623127934891ms
200000条,导入用时:517ms
200000条,开始导入到数据库时间:1623127940189ms
200000条,结束导入到数据库时间:1623127940677ms
200000条,导入用时:488ms
200000条,开始导入到数据库时间:1623127946402ms
200000条,结束导入到数据库时间:1623127946925ms
200000条,导入用时:523ms
200000条,开始导入到数据库时间:1623127952158ms
200000条,结束导入到数据库时间:1623127952639ms
200000条,导入用时:481ms
200000条,开始导入到数据库时间:1623127957880ms
200000条,结束导入到数据库时间:1623127958925ms
200000条,导入用时:1045ms
200000条,开始导入到数据库时间:1623127964239ms
200000条,结束导入到数据库时间:1623127964725ms
200000条,导入用时:486ms
------结束读取Excel的Sheet时间(包括导入数据过程):1623127964725ms------

Ver si los datos en la base de datos están realmente almacenados en 300w

Se puede ver que los datos son 300 W más que antes de importar, y la prueba es muy exitosa

 

3.3.4 Resumen de importación

Específicamente, no miré las pruebas de otras personas en Internet. Generalmente, pocas personas están dispuestas a probar esto, pero esta velocidad fue suficiente para mí para resolver la importación y exportación de big data de la empresa en ese momento. Por supuesto , la lógica comercial de la empresa es muy complicada y la cantidad de datos es relativamente grande. Hay muchos y hay muchos campos en la tabla. La velocidad de importación y exportación será más lenta que la prueba actual, pero también está dentro el rango aceptable de seres humanos.

4 Resumen

Los problemas encontrados en este trabajo también me dejaron una profunda impresión, y también es un punto culminante de mi carrera.

Como mínimo, puede escribir en su currículum que ha procesado millones de datos de importación y exportación.

Finalmente, permítanme hablar sobre lo que la compañía hizo antes. La práctica anterior de la compañía era

Limite la cantidad de descargas por parte de los usuarios, y solo cuatro personas pueden descargar al mismo tiempo a la vez, y controle los datos máximos de exportación de cada usuario a un máximo de 20 W. Al mismo tiempo, también usan JDBC para importar en lotes , pero no controlan manualmente las transacciones .

Puedo entender controlar la cantidad de descargas simultáneas, pero controlar los datos de descarga a un máximo de 20w parece un poco de mal gusto.

Este también es un problema que resolveré más adelante.

Supongo que te gusta

Origin blog.csdn.net/wokoone/article/details/127577680
Recomendado
Clasificación