Оптимизация в предложении Postgresql для более чем 3000 значений

#excel #postgresql #spring-boot #spring-data-jpa

#преуспеть #postgresql #пружинный ботинок #spring-data-jpa #excel #весенняя загрузка

Вопрос:

У меня есть приложение, в котором пользователь будет загружать файл Excel (.xlsx или .csv) с более чем 10 000 строками с одним столбцом «PartID», содержащим значения для поиска в базе данных

Я буду считывать значения Excel и сохранять их в объекте list и передавать список в качестве параметра в метод поиска репозитория Spring Boot JPA, который встроен в запрос предложения внутри:

                 // Read excel file
                stream = new   ByteArrayInputStream(file.getBytes());
                wb = WorkbookFactory.create(stream);
                org.apache.poi.ss.usermodel.Sheet sheet = wb.getSheetAt(wb.getActiveSheetIndex());
                
                Iterator<Row> rowIterator = sheet.rowIterator();
                
                while(rowIterator.hasNext()) {
                    Row row = rowIterator.next();
                    Cell cell = row.getCell(0);
                    System.out.println(cell.getStringCellValue());
                    vinList.add(cell.getStringCellValue());
                }
                
                //JPA repository method that I used
                  findByPartIdInAndSecondaryId(List<String> partIds);
  

Я читал во многих статьях и испытал то же самое в приведенном выше случае, что использование IN query неэффективно для огромного списка данных.

Как я могу оптимизировать приведенный выше сценарий или написать новый оптимизированный запрос?

Кроме того, пожалуйста, дайте мне знать, есть ли оптимизированный способ чтения файла Excel, отличный от вышеупомянутого фрагмента кода

Это было бы очень полезно!! Заранее спасибо!

Комментарии:

1. В Stackoverflow есть примеры использования VALUES соединения вместо if in . Вы пробовали это?

2. @madflow, я пробовал это. Я хотел бы знать, есть ли какой-либо другой оптимизированный способ сделать для огромного списка значений

3. @LaurenzAlbe, поскольку я буду получать списки из пользовательского интерфейса через API, я обязан перемещать большие списки между приложением и базой данных. Я не знаю, как эффективно передать список

4. @LaurenzAlbe, боюсь, мне не совсем понятно ваше утверждение:(. Не могли бы вы поделиться каким-либо примером запроса?

Ответ №1:

Если список действительно огромен, вы никогда не будете молниеносными.

Я вижу несколько вариантов:

  1. Отправьте запрос с большим IN списком, как вы упомянули в своем вопросе.

  2. Создайте оператор, который является объединением с большим VALUES предложением:

     SELECT ... FROM mytable
       JOIN (VALUES (42), (101), (43), ...) AS tmp(col)
          ON mytable.id = tmp.col;
      
  3. Создайте временную таблицу со значениями и присоединитесь к ней:

     BEGIN;
    CREATE TEMP TABLE tmp(col bigint) ON COMMIT DROP;
      

    Тогда либо

     COPY tmp FROM STDIN; -- if Spring supports COPY
      

    или

     INSERT INTO tmp VALUES (42), (101), (43), ...; -- if not
      

    Затем

     ANALYZE tmp;  -- for good statistics
    SELECT ... FROM mytable
       JOIN tmp ON mytable.id = tmp.col;
    COMMIT;  -- drops the temporary table
      

Какой из них самый быстрый, лучше всего определяется методом проб и ошибок для вашего случая; Я не думаю, что можно сказать, что один из методов всегда будет превосходить другие.

Некоторые соображения:

  • Решения 1. и 2. могут привести к очень большим операторам, в то время как решение 3. может быть разделено на более мелкие части.

  • Решение 3. скорее всего, будет медленнее, если список не будет действительно большим.

Комментарии:

1. Большое вам спасибо! Я попробую все эти способы и обновлю статус каждого решения.