Как ускорить процесс обновления / вставки Oracle через Java? - PullRequest
6 голосов
/ 02 февраля 2011

Я столкнулся с проблемой в моей компании, которая заключается в том, что скорость нашей программы недостаточно высока.Если быть более точным, то мы являемся телекоммуникационной компанией, и эта программа обрабатывает транзакции вызова / интернет-серфинга, совершаемые всеми пользователями мобильных телефонов в нашем городе.Поскольку объем загружаемого контента пользователями iphone слишком велик, наша программа не может обработать их достаточно быстро.

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

Я искал в Интернете и просматривал некоторые сайты (например: http://www.javaperformancetuning.com/tips/rawtips.shtml), говоря о производительности Java в БД, ноЯ не могу найти предложение, подходящее для нас.

Эти советы не применимы / уже используются, например:

1.Используйте готовые заявления.Использовать параметризованный SQL

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

2.Настройте SQL для минимизации возвращаемых данных (например, не «SELECT *»).

Конечно, уже используется.

3.Используйте пул соединений.

Мы удерживаем одно соединение во время выполнения программы.И я сомневаюсь, что объединение в пул не может решить проблему, потому что наша программа действует как 1 пользователь, поэтому нет проблем для одновременного доступа к БД.Если кто-то из вас думает, что объединение это хорошо, пожалуйста, скажите мне, почему.Спасибо.

4.Попробуйте объединить запросы и пакетные обновления.

Невозможно это сделать.Каждый запрос / вставка / обновление зависит от информации базы данных.Например, мы ищем в БД информацию о клиенте, если мы не можем найти его использование, мы вставляем его в БД, в противном случае мы делаем обновление.

5.По завершении закройте ресурсы (Соединения, Операторы, Наборы результатов)

Конечно.

6.Выберите самый быстрый драйвер JDBC.

Я не знаю.Я ищу в Интернете тип водителя, и я очень запутался.Мы используем oracle.jdbc.driver.OracleDriver, и мы используем тонкий вместо oci, это все, что я знаю.Кроме того, наша программа является двухуровневой (java <-> oracle)

7.Отключите автоматическую фиксацию

, которая уже сделала это.

Ожидание любой помощи.

Ответы [ 7 ]

10 голосов
/ 02 февраля 2011

4.Попробуйте объединить запросы и пакетные обновления.

Невозможно это сделать.Каждый запрос / вставка / обновление зависит от информации базы данных.Например, мы ищем в БД информацию о клиенте, если мы не можем найти его использование, мы вставляем использование в БД, в противном случае мы делаем обновление.

Если вы делаете это из приложения JavaВы можете улучшить производительность, сделав это в базе данных за один прием.Есть несколько способов:

1) Использовать оператор SQL MERGE

2) Написать хранимую процедуру для выполнения логики вставки или обновления и просто вызвать ее изJava.

Дальнейшее объяснение

Я предполагаю из того, что вы сказали, что на данный момент у вас есть логика Java, которая работает следующим образом:

// Pseudocode
execute SQL 'select count(*) from mytable where id=?'
if result = 0 then
    execute SQL 'insert into mytable (id,a,b,c) values (?,?,?,?)';
else
    execute SQL 'update mytable set a=?, b=?, c=? where id=?';
end if;

Это означает, что 2 отдельных раундапоездки в базу данных: один для проверки существования записи, а другой для вставки или обновления в зависимости от ситуации.

Альтернативы:

1) Используйте оператор SQL MERGE:

// Pseudocode
execute SQL 'merge into mytable t using (select ? id, ? a, ? b, ? c from dual) s
             on (t.id = s.id)
             when matched then update set t.a = s.a, t.b = s.b, t.c = s.c
             when not matched then insert (id, a, b, c)
                  values (s.id, s.a, s.b, s.c)';

Поначалу оператор MERGE немного устрашает, особенно когда вам нужно использовать «двойную» таблицу Oracle.

2) Использовать хранимую процедуру:

// Pseudocode
execute SQL 'begin mytable_package.insert_or_update
              (p_id => ?, p_a => ?, p_b => ?, p_c => ?); end;'

Хранимая процедура в пакете с именем mytable_package будет выглядеть примерно так:

procedure insert_or_update (p_id mytable.id%type
                           ,p_a  mytable.a%type
                           ,p_b  mytable.a%type
                           ,p_c  mytable.a%type
                           )
is
begin
    update mytable
    set    a = p_a, b = p_b, c = p_c
    where  id = p_id;
    if sql%rowcount = 0 then
        insert into mytable (id, a, b, c) values (p_id, p_a, p_b, p_c);
    end if;
end;
6 голосов
/ 02 февраля 2011

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

4) Попробуйте объединить запросы и пакетные обновления.

Невозможно это сделать.Каждый запрос / вставка / обновление зависит от информации базы данных.Например, мы ищем в БД информацию о клиенте, если мы не можем найти его использование, мы вставляем его в БД, в противном случае мы делаем обновление.

На ум приходят две вещи:

  • Сделайте инструкцию UPDATE и проверьте результат ExecuteUpdate ();только если он равен нулю, вставьте.Сохраняет один оператор SELECT.

  • Всегда (возможно, пакетная) вставка в промежуточную таблицу, позже используйте оператор MERGE для обновления таблицы использования.

5) Закрывать ресурсы (Соединения, Операторы, ResultSets) по окончании

Держать соединение открытым как можно дольше (т.е. постоянно до отключения сервера)), подготовьте PreparedStatement один раз и используйте его несколько раз.


Выполните небольшую агрегацию перед записью в базу данных.Пользователь сотового телефона, который генерирует транзакцию сейчас, вероятно, создаст другую в течение нескольких секунд.Используйте хеш-таблицу для агрегирования текущего использования и запишите ее в базу данных через минуту или около того.

4 голосов
/ 02 февраля 2011

Получите копию Профессиональное программирование Oracle .

В 2005 году это выглядит немного по-старому, но Oracle не претерпевает существенных изменений, когдаречь идет об оптимизации производительности.Я сам получил эту книгу и использовал ее для ускорения, казалось бы, неразрешимых проблем с производительностью для многих приложений.Возьми.Прочитайте это.Сделайте это.

Итак, что вы можете сделать, пока ждете экспресс-доставки?

  • Получите БД на вашей стороне, - вам понадобится их помощьи их инструменты
  • Возьмите TOAD и, при необходимости, заплатите за дополнительные инструменты анализа запросов
  • Проверяйте свои индексы для каждого выполняемого запроса - вам необходимо тщательно изучить планы выполнения (AUTOTRACE иEXPLAIN PLAN - ваши друзья здесь)
  • Рассмотрите тип используемого вами индекса (может ли функциональный индекс помочь?)
  • Рассмотрите возможность использования переносимых табличных пространств
  • Используйтевстроенный оптимизатор для сбора информации
  • Получение статистики, позволяющей измерять прирост производительности (независимо от предварительного кэширования и т. п.)
  • Рассматривать сохраненные схемы
  • Рассмотрим материализованные представления, позволяющие разделить ваши данные на те, которые необходимы немедленно и на которые может возникнуть задержка
  • Рассмотрим усечение таблицы, чтобы уменьшить размер общего числа.l таблицы, поскольку старые данные отбрасываются

Этого должно быть достаточно, чтобы дать вам четкое представление о том, что не работает, и о том, как это исправить.

3 голосов
/ 02 февраля 2011

Прежде всего вам нужны администраторы баз данных на вашей стороне , чтобы сообщить вам, где на самом деле тратится время. Вы можете быть молниеносными в своем клиенте и по-прежнему иметь длительное время транзакций, пока не будет установлен критический индекс.

Прошло восемь лет с тех пор, как я работал с Java + Oracle, но тогда я не обнаружил, что драйвер oci (использующий собственный драйвер в DLL) значительно быстрее, чем тонкий драйвер (все написано на Java).

Быстрое решение проблемы - это создать текстовый файл с 1000 или 10000 транзакциями одновременно и позволить SQLLDR внедрить пакет в базу данных. Возможно, даже больше. Правильно вызванный SQLLDR - это самая быстрая вещь, и он выиграет вам время, чтобы сделать это правильно.

0 голосов
/ 09 февраля 2011

Если вы хотите, чтобы участие администратора баз данных было минимальным, вы можете, по крайней мере, запросить логин для доступа к Oracle Enterprise Manager, работающему на тестовом сервере. В OEM вы можете увидеть, какие операции занимают много времени. OEM также постарается помочь вам, предложив способы повышения производительности, такие как добавление индексов или изменение структуры ваших запросов. Надеемся, что OEM может, по крайней мере, дать вам веские основания для того, чтобы просить администраторов базы данных о дальнейшем участии.

0 голосов
/ 08 февраля 2011

Можете ли вы разделить рабочую нагрузку, чтобы использовать несколько сеансов для базы данных? Есть много обращений к базе данных, что приводит к задержке. Если ваши таблицы структурированы правильно, они могут обрабатывать несколько одновременных вставок / обновлений без проблем (проверьте, чтобы свойство INITRANS тяжелых вставленных таблиц совпадало с количеством одновременных сеансов, выполняющих вставку). Я думаю, что это был бы самый простой способ выиграть производительность для вашего приложения. Какая версия базы данных используется? Вы можете получить отчеты ADDM? Они могут мгновенно сказать вам, что, если есть, проблема в базе данных. Достаточно ли ресурсов процессора у сервера приложений? Если нет, это дополнительная причина для распределения нагрузки по нескольким сеансам, в этом случае по нескольким серверам приложений. Без отчета statspack или - предпочтительно - отчета ADDM трудно сказать, где проблема.

Надеюсь, это поможет, Рональд.

0 голосов
/ 02 февраля 2011

Запускаете ли вы новые экземпляры JVM для каждого выполнения? Можете ли вы уточнить характер вашего приложения (то есть, как оно вызывается, что вызывает вызов и т. Д.). Из вашего описания, это на самом деле не звучит как проблема Java и БД. Похоже, что это какая-то проблема с индексом базы данных или другая проблема дизайна Какова природа команд SQL, которые вы используете? Вы рассчитывали или профилировали эти звонки, чтобы увидеть, что некоторые из них занимают больше времени, чем другие?

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