Производительность Oracle CLOB - PullRequest
       17

Производительность Oracle CLOB

9 голосов
/ 06 октября 2009

Я выполняю запросы к Oracle 10g с JDBC (используя последние драйверы и UCP в качестве источника данных) для получения CLOB (в среднем 20 000 символов). Тем не менее, производительность кажется довольно плохой: пакетный поиск 100 больших объектов занимает в среднем 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 ]

6 голосов
/ 07 октября 2009

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

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

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

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

Удачи

6 голосов
/ 07 октября 2009

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

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

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

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

5 голосов
/ 17 апреля 2014

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

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

statement1.setFetchSize(1000);
if (statement1 instanceof OracleStatement) {
    ((OracleStatement) statement1).setLobPrefetchSize(250000);
}
2 голосов
/ 12 октября 2009

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

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

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

...