Как эффективно записать 1 миллион объектов в файл CSV? - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь записать CSV-файл, содержащий миллион записей в моей базе данных.У меня есть общее количество 8 миллионов записей в базе данных, каждая запись имеет 5 атрибутов. Итак, файл CSV будет иметь 8 миллионов строк и 5 столбцов.Мне нужно сделать это наиболее эффективным способом, но я не могу пойти меньше чем за 4 минуты, чтобы написать только 1 миллион.Я пытался увеличить размер буферизированного писателя, я также пытался использовать напрямую файловый писатель, но я получил 4 минуты.Есть ли улучшения для моего кода?

Мой код:

@Component
public class SaveCSVAdminImsiHelper {

    @Autowired
    private Environment environment;

    @Autowired
    private WmAdminImsisResourceHelper wmAdminImsisResourceHelper;

    @Autowired
    private WmPushedImsiService wmPushedImsiService;

    @PersistenceContext
    private EntityManager entityManager;

    private List<String> imsisCsvColumns;

    private Logger imsiLogger = LoggerFactory.getImsiLogger(this.getClass().getName());

    private void initCsvColumns() {
        imsisCsvColumns = new ArrayList<>();
        imsisCsvColumns.add(environment.getProperty("CSV_IMSINUMBER"));
        imsisCsvColumns.add(environment.getProperty("CSV_USERNAME"));
        imsisCsvColumns.add(environment.getProperty("CSV_STARTDATE"));
        imsisCsvColumns.add(environment.getProperty("CSV_EXPIREDATE"));
        imsisCsvColumns.add(environment.getProperty("CSV_DIRTY"));
    }

    private void formatAndWriteField(BufferedWriter writer, String field, char separator, boolean isLastField) throws IOException {
        field = field.replace("\"", "\"\"");

        if (field.indexOf(separator) > -1 || field.indexOf('"') > -1) {
            field = '"' + field + '"';
        }

        writer.append(field);
        if (!isLastField) {
            writer.append(separator);
        }
    }

    private void writeColumnsTitle(BufferedWriter writer, List<String> columnsTitle, char separator) throws IOException {
        for (Iterator<String> keysIterator = columnsTitle.iterator(); keysIterator.hasNext();) {
            String column = keysIterator.next();

            if (keysIterator.hasNext()) {
                formatAndWriteField(writer, column, separator, false);
            } else {
                formatAndWriteField(writer, column, separator, true);
            }
        }
        writer.newLine();
    }

    private String checkForImsiDirty(WmPushedImsi wmPushedImsi) {
        return (wmPushedImsi.getFailedPushBatch() != null || wmPushedImsi.getFailedDeleteBatch() != null) ? "Yes" : "No";
    }


    private void writeImsiProperties(BufferedWriter writer, List<WmPushedImsi> wmPushedImsis, char separator) throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (WmPushedImsi wmPushedImsi : wmPushedImsis) {
            formatAndWriteField(writer, wmPushedImsi.getImsiNumber(), separator, false);
            formatAndWriteField(writer, wmPushedImsi.getUsername(), separator, false);
            formatAndWriteField(writer, simpleDateFormat.format(wmPushedImsi.getStartDate()), separator, false);
            formatAndWriteField(writer, simpleDateFormat.format(wmPushedImsi.getExpireDate()), separator, false);
            formatAndWriteField(writer, checkForImsiDirty(wmPushedImsi), separator, true);
            writer.newLine();
        }
    }

    private File writeFinalCsv(String fileName, char separator, WmAdminImsisResource wmAdminImsisResource) throws Exception {
        File file = new File(fileName);
        int PAGE_SIZE = 300_000;
        Map<String, String> filterMap = wmAdminImsisResourceHelper.createFilteringProperties(wmAdminImsisResource);
        Map<String, String> sortingMap = wmAdminImsisResourceHelper.createSortingProperties(wmAdminImsisResource);

        long pages = wmPushedImsiService.countAllWithSortCriteriaAndFilter(filterMap) / PAGE_SIZE;
        initCsvColumns();
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file), 31457280)) {

            writeColumnsTitle(writer, imsisCsvColumns, separator);

            for (int page = 0; page <= pages; page++) {
                List<WmPushedImsi> wmPushedImsis = wmPushedImsiService.findAllWithSortCriteriaAndFilter(filterMap, sortingMap, page, PAGE_SIZE);
                writeImsiProperties(writer, wmPushedImsis, separator);
                entityManager.getEntityManagerFactory().getCache().evictAll();
            }
        } catch (IOException e) {
            imsiLogger.log(Level.SEVERE, environment.getProperty("wlm.error.failedToSaveCsv"), e);
        }

        return file;
    }

    private void createImsiZip(WmAdminImsisResource wmAdminImsisResource, File imsiCsvZip, String fileNameWithoutExtension) throws Exception {
        try (FileOutputStream fileOutputStream = new FileOutputStream(imsiCsvZip.getCanonicalFile());
                ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)) {
            imsiCsvZip.deleteOnExit();

            String fileName = fileNameWithoutExtension + environment.getProperty("CSVEXTENSION");
            File imsisCsv = writeFinalCsv(fileName, ',', wmAdminImsisResource);
            String fileNameInZip = environment.getProperty("CSVNAME") + environment.getProperty("CSVEXTENSION");
            WsUtils.addFileToZipWithOtherName("", imsisCsv, zipOutputStream, fileNameInZip);
            if (imsisCsv.exists()) {
                imsisCsv.delete();
            }

        } catch (IOException e) {
            imsiLogger.log(Level.SEVERE, environment.getProperty("wlm.error.failedToSaveCsv"), e);
        }
    }

    public String downloadImsiCsvZip(WmAdminImsisResource wmAdminImsisResource, StringBuilder stringBuilder) {
        try {
            String path = "";
            String html = environment.getProperty("HTML") + File.separator;
            String htmlCsv = html + environment.getProperty("CSV") + File.separator;
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
            String startPath = environment.getProperty("STARTPATH") + File.separator;
            File csvDirectory = new File(htmlCsv);
            if (!csvDirectory.exists()) {
                csvDirectory.mkdir();
            }
            csvDirectory.deleteOnExit();
            String fileNameWithoutExtension = htmlCsv + environment.getProperty("CSVNAME") + simpleDateFormat.format(new Date());
            File imsisCsvZip = new File(fileNameWithoutExtension + environment.getProperty("ZIPEXTENSION"));
            createImsiZip(wmAdminImsisResource, imsisCsvZip, fileNameWithoutExtension);
            if (imsisCsvZip.exists()) {
                path = imsisCsvZip.getPath();
            }
            if (path.startsWith(html)) {
                path = path.substring(html.length());
            }
            path = path.replaceAll("\\\\", "/");

            return startPath + path;
        } catch (Exception e) {
            imsiLogger.log(Level.SEVERE, environment.getProperty("wlm.error.failedToSaveCsv"), e);
            stringBuilder.append(e);
        }
        return "";
    }



}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...