Вопрос

Я запускаю запросы к Oracle 10g с помощью JDBC (используя последние версии драйверов и UCP в качестве источника данных), чтобы получить CLOBs (среднее значение.20 тысяч символов).Однако производительность, похоже, довольно плохая:пакетное извлечение 100 LOBs занимает в среднем 4 секунды.Судя по моим наблюдениям, эта операция также не связана ни с вводом-выводом, ни с процессором, ни с сетью.

Моя тестовая настройка выглядит следующим образом:

PoolDataSource dataSource = PoolDataSourceFactory.getPoolDataSource();
dataSource.setConnectionFactoryClassName("...");
dataSource.setConnectionPoolName("...");
dataSource.setURL("...");
dataSource.setUser("...");
dataSource.setPassword("...");

dataSource.setConnectionProperty("defaultRowPrefetch", "1000");
dataSource.setConnectionProperty("defaultLobPrefetchSize", "500000");

final LobHandler handler = new OracleLobHandler();
JdbcTemplate j = new JdbcTemplate(dataSource);

j.query("SELECT bigClob FROM ...",

        new RowCallbackHandler() {

            public void processRow(final ResultSet rs) throws SQLException {

                String result = handler.getClobAsString(rs, "bigClob");

            }

        });

}

Я экспериментировал с размерами выборки, но безрезультатно.Я делаю что-то не так?Есть ли способ ускорить извлечение CLOB при использовании JDBC?

Это было полезно?

Решение 4

Спасибо за все полезные предложения.Несмотря на то, что я помечен как ответ на проблему, мой ответ заключается в том, что, похоже, хорошего решения нет.Я пробовал использовать параллельные операторы, разные характеристики хранилища, предварительно заданную температуру.столы и другие вещи.Операция, по-видимому, не привязана к какой-либо характеристике, видимой по следам или планам объяснения.Даже параллелизм запросов кажется отрывочным, когда задействованы CLOBs.

Несомненно, были бы лучшие варианты для работы с большими сбросами (особенно сжатием) в среде 11g, но atm.Я застрял с 10g.

Теперь я выбрал дополнительный обратный путь к базе данных, в котором я предварительно обработаю CLOBs в двоичный RAW-файл с оптимизированным размером.В предыдущих развертываниях это всегда было очень быстрым вариантом и, вероятно, будет стоить проблем с поддержанием автономного вычисляемого кэша.Кэш будет признан недействительным и обновляться с использованием постоянного процесса и AQ до тех пор, пока кто-нибудь не придумает идею получше.

Другие советы

Мой прошлый опыт использования данных типа oracle LOB для хранения больших объемов данных не был хорошим.Это нормально, когда он находится под 4k, так как он хранит его локально, как varchar2.Как только он превышает 4k, вы начинаете видеть снижение производительности.Возможно, ситуация улучшилась с тех пор, как я в последний раз пробовал это пару лет назад, но вот то, что я нашел в прошлом, к вашему сведению:

Поскольку клиентам необходимо получать LOBs через oracle server, вы можете рассмотреть следующую интересную ситуацию.

  • данные lob будут конкурировать с ограниченным SGA-кэшем с другим типом данных, если oracle решит их кэшировать.Поскольку данные clob являются в целом большими, поэтому они могут передавать другие данные
  • данные большой емкости плохо считываются с диска, если oracle решает не кэшировать их и передает данные клиенту в потоковом режиме.
  • фрагментация - это, вероятно, что-то такое с чем вы еще не сталкивались.Вы увидите, удаляют ли ваши приложения lob, и oracle попытается повторно использовать lob.Я не знаю, поддерживает ли oracle онлайн-дефрагментацию диска для lob (у них есть для индексов, но это занимает много времени, когда мы пробовали это ранее).

Вы упомянули 4s за 100 lobs в среднем 20k, так что это 40 мс на lobs.Помните, что каждый объект должен быть извлечен через отдельный локатор объектов (по умолчанию его нет в результирующем наборе).Я предполагаю, что это дополнительная поездка туда и обратно для каждого lob-объекта (я не уверен в этом на 100%, поскольку это было некоторое время назад), если это так, я предполагаю, что это займет не менее 5 мс дополнительного времени на поездку туда и обратно в последовательном порядке, верно?Если это так, то ваша производительность уже сначала ограничена последовательными выборками больших объектов.Вы должны быть в состоянии убедиться в этом, отслеживая время, затраченное на выполнение sql, по сравнению с извлечением содержимого lob.Или вы можете проверить это, исключив столбец lob, как предложено в предыдущем ответе в сообщении, который должен сообщить вам, связан ли он с lob.

Удачи

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

Есть ли Order By в запросе?10 Тысяч строк - это довольно много, если их нужно отсортировать.

Кроме того, извлечение PK не является справедливым тестом по сравнению с извлечением всего CLOB.Oracle хранит строки таблицы, которых, вероятно, много в блоке, но каждый из CLOBS (если они > 4K) будет храниться вне строки, каждый в серии блоков.Таким образом, сканирование списка PK будет быстрым.Кроме того, в PK, вероятно, есть индекс, поэтому Oracle может просто быстро сканировать блоки индекса и даже не обращаться к таблице.

4 секунды действительно кажутся немного завышенными, но это 2 МБ, которые должны быть прочитаны с диска и переданы по сети в вашу Java-программу.Сеть может быть проблемой.Если вы выполните SQL-трассировку сеанса, это укажет вам, где именно тратится время (чтение с диска или по сети).

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

Начиная с драйвера Oracle 11.2g JDBC, вы можете использовать предварительную выборку.Это ускорило доступ в 10 раз...

statement1.setFetchSize(1000);
if (statement1 instanceof OracleStatement) {
    ((OracleStatement) statement1).setLobPrefetchSize(250000);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top