Мне нужно зациклить более 50 миллионов строк в Oracle и выполнить некоторую обработку. Я получаю строки, используя простой запрос «Выбрать и упорядочить по».
Сначала я использовал программу чтения JDBC на основе курсора, чтобы не получать все результаты сразу, а получать их по мере продвижения цикла. Однако запрос выбора вызвал еще одну проблему, когда Oracle выдал ошибку ORA-01652: unable to extend temp segment by 128 in tablespace TEMP
, вероятно, потому, что он не может хранить набор результатов запроса выбора в пространстве TEMP.
Другой вариант, который у меня есть, — это разбиение на страницы набора ключей. Чтобы прочитать первую страницу, я прикреплю следующее предложение FETCH NEXT 5000 ROWS ONLY
в конце того же запроса Select, о котором я упоминал выше.
Вопрос: Будет ли это работать? Или я получу тот же результат, потому что ему все равно придется пройти и получить все результаты и получить первые 5000 строк?
Мне также нужно сделать вызов API для обработки данных, которые я делаю из процесса Java.
Вы также можете использовать SQL в вызове API. И просто чтобы дать вам представление о том, о чем я говорю: если бы я хотел обновить статус всех продуктов, когда они встречаются в 50 миллионах строк позиций заказа, я бы мог update product set status = 'ordered' where product_id in (select product_id from order_position)
. Поэтому вместо того, чтобы использовать язык программирования для циклического перебора 50 миллионов позиций заказов и обработки продуктов, я просто использую SQL, который в миллион раз быстрее. Это, конечно, просто пример. Что вы делаете с этими 50 миллионами строк в цикле? Разве ты не можешь использовать SQL?
Хорошо, это фиктивный пример, потому что я не могу разместить здесь реальный код, потому что нам это не разрешено. Мы делаем гораздо больше в процессе до и после вызова API, требуя определенных библиотек со встроенной логикой. Но я не знал, что мы можем сделать вызов API из PLSQL, поскольку я когда-либо использовал только для простых вещей.
API — это набор функций. Вы можете написать кучу функций PL/SQL и назвать это API. Или используйте любой другой язык программирования, имеющий интерфейс SQL (я думаю, что большинство из них имеют). И все, что я говорю, это то, что с базой данных вы обычно не обрабатываете ее с помощью языков программирования в циклах, а скорее используете SQL на основе наборов.
Ах, под вызовом API я имел в виду HTTP-запрос к другой службе, но я погуглил, кажется, что это тоже возможно, но вызов будет затруднительным. Но я понял вашу точку зрения, учту в следующий раз.
Да, использование пагинации набора ключей, скорее всего, поможет вам избежать ошибки ORA-01652, поскольку для получения первых 5000 строк Oracle не требует одновременной загрузки и сортировки всех 50 миллионов строк. Вместо этого он извлекает строки меньшими порциями на основе указанного вами ключа (например, столбца идентификатора), что уменьшает необходимый объем временного хранилища (пространства TEMP).
Вот почему это работает лучше:
Эффективность: разбиение на страницы набора ключей ищет строки только после последней полученной строки, что ускоряет процесс и требует меньше места TEMP. Использование индекса: лучше всего работает, когда у вас есть индекс по столбцу, по которому вы упорядочиваете. Таким образом, Oracle может быстро найти следующий пакет строк, не сканируя всю таблицу. Однако убедитесь, что ваш запрос хорошо оптимизирован, и рассмотрите возможность увеличения табличного пространства TEMP, если вы все еще достигаете ограничений. Кроме того, убедитесь, что столбцы, которые вы используете для сортировки и нумерации страниц, проиндексированы, чтобы ускорить работу и еще больше сократить использование пространства TEMP.
Это создано ИИ?
я для тебя похож на ай?
Пагинация не поможет.
Вы получаете ORA-01652
, потому что ваш ORDER BY
использует рабочую область, которая перешла из PGA во временное пространство, а ваше табличное пространство TEMP
недостаточно велико, чтобы вместить временные сегменты, необходимые для завершения сортировки. 50 миллионов строк и все выбранные столбцы означают очень большие временные сегменты.
Чтобы решить проблему, вы можете выполнить одно из следующих действий:
TEMP
(разумный запрос).pga_aggregate_target
, если v$pgastat
.global memory bound
< 1 ГБ) или установив политику рабочей области вручную и определив sort_area_size
самостоятельно, но это не рекомендуемый метод, поскольку вы можете легко использовать слишком много памяти).ORDER BY
должен выполнить сканирование по возрастанию индекса вообще без какой-либо операции сортировки. Обратной стороной является то, что это сканирование индекса, что означает чтение одного блока для следования связанному списку от листового блока к листовому блоку, поэтому оно менее эффективно, чем прямое чтение по пути всего сегмента.parallel
с соответствующим DOP). При работоспособном DOP каждый подчиненный PX получает собственное распределение PGA (до 1 ГБ каждый при автоматической политике и 2 ГБ при ручной политике), поэтому вы можете использовать гораздо больше памяти PGA для сортировки (и, следовательно, меньше временного пространства), чем при последовательном процессе. .WHERE
, который собирает только часть необходимых данных и продвигает их программно. Это уменьшает количество входных данных в операцию сортировки и, следовательно, может быть адаптировано к доступному пространству TEMP
, но это очень неэффективно, поскольку вам придется повторно сканировать таблицу при каждом запросе. Всегда лучше взять все необходимое за один раз. Хотя вы можете удалить это повторное сканирование с помощью индекса, вы вернетесь к неэффективности, упомянутой выше в пункте 4.ORDER BY
. Вам действительно нужны отсортированные результаты? Большинство программных фрагментов этого не делают.Все вышеизложенное вам следует обсудить со своим администратором базы данных, который должен знать, сколько доступной памяти на хосте(ах) базы данных для PGA, сколько места доступно для расширения TEMP
, какую доступность ЦП можно предложить. соответствующий уровень параллелизма (DOP) и т. д.
Будет ли присоединение FETCH NEXT 5000 ROWS ONLY по-прежнему получать все строки в пространство TEMP, или оракул будет управлять этим каким-то образом, как упоминалось в других ответах, используя только идентификаторы и т. д.?
@humbleCoder, FETCH NEXT..
просто выполняет вычисления за вас, но не меняет основную динамику. Если столбец, по которому вы упорядочиваете данные, не индексируется в соответствии с сортировкой, вы будете выполнять полную сортировку 100% таблицы при каждом выполнении, поэтому разбиение на страницы повредит вам из-за повторной сортировки. Если он проиндексирован, чтобы избежать сортировки, вам следует избегать сортировки даже без нумерации страниц, но см. № 4 выше. Вы не хотите использовать индекс на этом томе. Слишком много операций чтения одного блока. Я сам никогда не находил реального применения нумерации страниц в стиле FETCH NEXT
, кроме как для отображения пользователем.
Администратор базы данных согласился увеличить пространство TEMP и придерживаюсь программы чтения на основе курсора, чтобы избежать всех проблем с нумерацией страниц.
Лучше запускать код рядом с данными, а затем запускать данные в коде. Как вы испытали. Java не подходит для манипулирования данными. База данных и SQL есть.
Сказал, что: «FETCH NEXT 5000 ROWS ONLY» приведет к снижению производительности на каждой странице. Например. первые несколько страниц будут быстро светиться. Несколько последних будут загружаться навсегда. Это связано с тем, что механизму базы данных потребуется прочитать 10 000 000 строк, чтобы вернуть строки между 10 000 000 и 10 005 000. Каждый ввод-вывод является дорогостоящим. Вот почему это должно иметь значение.
Стабильную производительность можно получить с помощью правильной индексации и предложения WHERE. Лучшее объяснение, которое я нашел: https://use-the-index-luke.com/blog/2013-07/pagination-done-the-postgresql-way. Пример предназначен для PostgreSQL, но будет работать с любой базой данных.
Для обработки данных я вызываю внешний API. Я не упомянул об этом, потому что думал, что это не имеет значения, но теперь, когда вы упомянули PLSQL, я упомянул об этом.
Да, для нумерации страниц я имею в виду ту же статью. Вопрос в том, будет ли FETCH NEXT 5000 ROWS ONLY с нумерацией страниц (о которой я упоминал в первоначальном вопросе) также замедляться после нескольких страниц?
Чтение 5000 строк всегда будет занимать одинаковое время. Важнейшая часть — быстро найти строку 1, 5001, 10001,... и начать читать интересующую вас 5000 строк. Вот почему так важна правильная индексация. Вы не хотите читать 49005000 строк и бросать их, чтобы найти 49005001 и прочитать последние 5000.
Цикл более 50 миллионов строк означает использование языка программирования. ПЛ/SQL? Разве вы не можете делать то, что хотите, с помощью простого SQL?