Как вставить 100 000 родительских строк каждая с 200 дочерними строками супер быстро? - PullRequest
2 голосов
/ 29 марта 2019

У меня есть родительская сущность с именем OrderEvent и дочерняя сущность с именем PreCondition.Один OrderEvent может иметь много предварительных условий (> = 200).Мне нужно сохранить 100000 OrderEvent + 100000 * 200 PreCondition.Я использовал Repository.save (список OrderEvents) и сохранял в БД для каждой 1000 записей.Требуется около 30 секунд, чтобы вставить 1000 OrderEvents.

Требуется почти час, чтобы сохранить все 100000 OrderEvents.

Есть ли способ сбить ниже 2 минут?

Попробовал сохранить сущности методом репозитория

    public  void parseOrder(String path, String collectionName) throws ParseException {
        BufferedReader reader;
        Connection conn = (Connection) em.unwrap(java.sql.Connection.class);
        System.out.println(conn);
        try {
            reader = new BufferedReader(new FileReader(
                    path));
            String line = reader.readLine();

            String jobNumber =  line.substring(0, 7).trim();
            String recordType =  line.substring(7, 9).trim();
            Integer len = line.length();
            preId = 0L;
            postId = 0L;
            eventId = 0L;

            OrderEvent orderEvent = this.paraseHeader(line,len,jobNumber,collectionName);
            Integer count = 1;
            Integer batch = 0;
            long startTime = System.nanoTime();

            List<OrderEvent> list = new ArrayList<OrderEvent>();
            while (line != null) {
                line = reader.readLine();
                if (line == null) {
                    continue;
                }
                jobNumber =  line.substring(0, 7).trim();
                recordType =  line.substring(7, 9).trim();
                len = line.length();

                if (recordType.equals("0H")) { 

                    count++;
                    batch++;
                    if (batch.equals(1000)) {
                        orderRepository.save(list);
                        list.clear();
                        long estimatedTime = System.nanoTime() - startTime;
                        System.out.println("Processed " +  batch + " records in " +  estimatedTime / 1_000_000_000.  +  " second(s).");

                        batch = 0;
                        startTime = System.nanoTime();
                    }


                    list.add(orderEvent);
                    //orderRepository.saveAndFlush(orderEvent);
                    orderEvent = this.paraseHeader(line,len,jobNumber,collectionName);

                } else if (recordType.equals("2F")) { 
                    this.paraseFeature(line,len,jobNumber,orderEvent);
                }
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private  OrderEvent paraseHeader (String line,Integer len,String jobNumber,String collectionName) throws ParseException {

            String model = line.substring(9, 16).trim();
            String processDate =  line.substring(len-11,len-3).trim();
            String formattedProcessDate =  processDate.substring(0,4) + "-" + 
                    processDate.substring(4,6) +"-" + processDate.substring(6,8) + " 00:00:00";

            //eventId++;

            OrderEvent orderEvent = new OrderEvent(jobNumber,UUID.randomUUID().toString(),collectionName,
                    formatter.parse(formattedProcessDate));

        //  preId++;
            //postId++;
            orderEvent.fillPrecondition("Model", "Stimulus", "OP_EQ", model);
            orderEvent.fillPostcondition("Add_Fact","Coded","Response","True");


            return orderEvent;
    }
    private  void paraseFeature (String line,Integer len, String jobNumber, OrderEvent orderEvent) {

    //  preId++;
        String feature = line.substring(len-7,len).trim();
        orderEvent.fillPrecondition("Feature", "Stimulus", "OP_EQ", feature);
    }

Ответы [ 3 ]

2 голосов
/ 29 марта 2019

Обычно это зависит от настройки базы данных, например, какова задержка для клиента, каковы индексы в таблицах, как запросы блокируют таблицу и т. Д.

Убедитесь, что вы понимаете, наскольковремя тратится на сетевые операции.Это может быть ограничивающим фактором, особенно если ваша база данных находится на другом конце света.

Сначала определите, какова задержка между клиентом и сервером базы данных.Если это 10 мс, то вставка этой строки за строкой будет: 100 000 * 200 * 10 мс = 200 000 с ~ 56 ч.Это очень медленно, поэтому убедитесь, что вы используете пакетные вставки с JDBC.

Иногда процесс вставки можно значительно ускорить, создав теневую таблицу:

  1. Создайте новые таблицы, идентичные таблицам OrderEvents и PreCondition.Некоторые СУБД допускают синтаксис CREATE TABLE ... AS SELECT ... FROM ....
  2. Отключение внешних ключей и индексов для теневых таблиц.
  3. Массовая вставка всех данных.
  4. Включение внешних ключей и индексов для теневых таблицстолы.Мы надеемся, что это гарантирует, что импортированные данные были правильными.
  5. Вставка из теневых таблиц в реальные таблицы, например, с помощью INSERT INTO ... SELECT ... FROM ....
  6. Удалить теневую таблицу.

Однако лучшим вариантом будет пропустить JDBC и переключиться на утилиту массовой загрузки, предоставляемую вашей базой данных, например, Oracle DB имеет Внешние таблицы и SQL * Loader .Эти инструменты специально разработаны для эффективного приема больших объемов данных, в то время как JDBC является интерфейсом общего назначения.

0 голосов
/ 29 марта 2019

В c # я могу использовать SqlBulkCopy для задач этого типа.

Может быть, в Java есть эквивалентный API .. Что-то вроде этого: com.microsoft.sqlserver.jdbc.SQLServerBulkCopy

0 голосов
/ 29 марта 2019

Что-то подобное лучше сделать, используя операцию BULK-обработки на сервере БД.Да, это совершенно другой процесс, но это займет несколько секунд.даже не минуты.

К сожалению, HOWTO сильно зависит от SQL-сервера

MS SQL: ОБЪЕМНАЯ НАСТРОЙКА: https://docs.microsoft.com/en-us/sql/t-sql/statements/bulk-insert-transact-sql?view=sql-server-2017

PostgreSQL: COPY: https://www.postgresql.org/docs/current/sql-copy.html

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