2014-09-15 3 views
0

У меня есть новое приложение, которое будет вставлять много данных и должно иметь возможность обрабатывать множество вставок в секунду. Схема базы данных состоит из двух таблиц: таблицы HEADER и DETAIL. Таблица HEADER содержит некоторую минимальную информацию, таблица DETAIL содержит большую часть данных, которые не будут обновляться.Вставка в две таблицы с минимальными накладными расходами

Запись HEADER имеет ограничение PK в поле идентификатора. Значение ID создается генератором последовательности вставки. Поле DETAIL.HEADER_ID имеет ограничение FK в поле HEADER.ID.

Мой вопрос: какой вариант будет выполнять самые быстрые вставки? Это будет работать на Weblogic 11g, Oracle 11g. Взгляд вверх 1000+ вставки/сек.

1) Используйте опцию JDBC Statement.RETURN_GENERATED_KEYS на вкладке HEADER, получите сгенерированный ключ, затем вставьте запись DETAIL.

2) Сначала вызовите последовательность.nextval, затем вставьте запись HEADER, затем вставьте запись DETAIL.

3) Как-то захватить блок идентификаторов последовательности, вставить все записи HEADER, а затем вставить все записи DETAIL. (как я могу захватить блок идентификаторов последовательности?).

+0

Лучший время для оптимизации никогда. Второе - лучшее время, когда у вас есть реальная проблема с производительностью. Время WORST во время разработки. Напишите самый простой и простой код, который вы, возможно, сможете. Не пытайтесь угадать, где будут узкие места в производительности - программное обеспечение тратит огромное количество времени в самых прочных местах! НЕ тратите огромное количество времени на ускорение своей Java - в конце концов, это вряд ли изменит ситуацию. Независимо от того, какой причудливый код Java-кода вы придумали, время INSERT базы данных будет доминировать во время выполнения. Поделитесь и наслаждайтесь. –

ответ

2

1)

я предлагаю использовать алгоритм HILO для генерации всех идентификаторов. Используйте разные последовательности для каждой таблицы. С размером распределения использования HILO alg около 1000. Это означает, что select nextval будет выполняться один раз для каждого 1000 записей.

2)

Использование JDBC пакетной вставки с размером, который является кратным размеру выделения хило. К примеру 2000, 3000 и т.д.

3)

Проверьте, если ваша БД может обрабатывать так много записей в одной транзакции. Если нет, вы, вероятно, должны зафиксировать tx после каждой вставки пакета.

-

Я использовал этот шаблон для переноса 300 млн записей на лету обработки Java из одной системы в другую. В некоторых таблицах скорость вставки была выше 5000 записей в секунду.

Ad 1) - реализация HILO

public interface IdentifierGenerator { 

    int getNextId(); 
} 

HiloGenerator:

public class HiLoSequenceGenerator implements IdentifierGenerator { 

    private String sequenceName; 
    private int allocationSize; 

    private IdentifierDao dao; 

    private boolean initialized; 
    private int min; 
    private int max; 
    private int next; 

    public HiLoSequenceGenerator() { 
    } 

    public HiLoSequenceGenerator(String sequenceName, int allocationSize, IdentifierDao dao) { 
     this.sequenceName = sequenceName; 
     this.allocationSize = allocationSize; 
     this.dao = dao; 
    } 

    @Override 
    public int getNextId() { 
     return next(); 
    } 

    private synchronized int next() { 

     if (!initialized) { 
      alloc(); 
      initialized = true; 
     } 

     if (next > max) { 
      alloc(); 
     } 

     return next++; 
    } 

    private void alloc() { 

     // fetch unique number from sequence 
     int unique = dao.getUniqueId(sequenceName); 

     // prepare buffer (pool of identifiers) 
     min = unique * allocationSize; 
     max = min + allocationSize - 1; 
     next = min; 

     if (log.isTraceEnabled()) { 
      log.trace("allocated id buffer based on " + sequenceName + ": [" + min + " - " + max + "]"); 
     } 
    } 

Здесь вы можете увидеть, как HILO работает с размером размещения 3 и блок Mockito тест:

public class HiLoSequenceGeneratorTest { 

    @Test 
    public void test() { 

     // given 
     IdentifierDao dao = mock(IdentifierDao.class); 
     when(dao.getUniqueId(anyString())).thenReturn(3, 4, 10, 11); 

     HiLoSequenceGenerator gen = new HiLoSequenceGenerator("seq", 3, dao); 

     // 3: 9, 10, 11 
     // 4: 12, 13, 14 
     //10: 30, 31, 32 
     //11: 33, 34, 35 

     // when - then 
     assertEquals(9, gen.getNextId());  // hit db 
     assertEquals(10, gen.getNextId()); 
     assertEquals(11, gen.getNextId()); 
     assertEquals(12, gen.getNextId());  // hit db 
     assertEquals(13, gen.getNextId()); 
     assertEquals(14, gen.getNextId()); 
     assertEquals(30, gen.getNextId());  // hit db 
     assertEquals(31, gen.getNextId()); 
     assertEquals(32, gen.getNextId()); 
     assertEquals(33, gen.getNextId());  // hit db 
     assertEquals(34, gen.getNextId()); 
     assertEquals(35, gen.getNextId()); 
    } 

} 
+0

Это интересная концепция. Я запустил это от нашего администратора баз данных и посмотрю, что они думают. – aglassman

+0

Обе вставки hilo alg и jdbc уменьшают количество запросов, отправляемых из jvm в базу данных, что повышает производительность. Btw, hilo alg, основанный на последовательности, является одним из самых популярных генераторов идентификаторов в Hibernate и JPA. –

Смежные вопросы