2009-10-06 4 views
8

Я запускаю запросы против Oracle 10g с помощью JDBC (используя последние версии драйверов и UCP в качестве DataSource), чтобы получить CLOB (около 20 тыс. Символов). Однако производительность кажется довольно плохим: пакетное извлечение 100 LOB занимает в среднем 4 секунды. Операция также не связана ни с I/O, ни с процессором, ни с сетью, судя по моим наблюдениям.Производительность Oracle CLOB

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

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?

+0

Как вы определили, что сеть не связана? Вы говорите о настройке нового JDBC-соединения (дорогого), данных на 2 Мб для чтения с диска, отправки его по сети и накладных расходов на запрос (который не указан). Я не знаю, все ли это 4s, в зависимости от вашего макета сети и настройки базы данных. – Gandalf

+0

Уточнение: я измеряю в * единицах * 100, поэтому первоначальный штраф за соединение не учитывается. Суммарная пропускная способность сети составляет менее 2 Мбит/с, поэтому я полагаю, что она не связана с сетью. – yawn

+0

Сколько времени занимает фактический запрос? – Gandalf

ответ

2

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

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

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

+0

Похоже, что обходным путем, как если бы вы извлекли 100 строк, вы будете оплачивать добавление туда и обратно, но сэкономить 100 обращений, полностью сэкономив 100-1 = 99 раундов. Но как вы его реализовали? – user451795

+0

Извлекая только CLOB + некоторый ключ, чтобы идентифицировать их позже и записать их в локальное хранилище ключей. Я использовал [Oracle Berkeley DB] (http://www.oracle.com/technetwork/database/berkeledb/overview/index.html), но вы можете легко использовать SQLite или что-нибудь еще, я полагаю. – yawn

6

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

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

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

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

5

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

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

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

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

Удача

3

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

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

statement1.setFetchSize(1000); 
if (statement1 instanceof OracleStatement) { 
    ((OracleStatement) statement1).setLobPrefetchSize(250000); 
}