Последовательность спящего оракула создает большой разрыв

Я использую hibernate 3, oracle 10g. У меня есть таблица: тема. Определение здесь

CREATE TABLE SUBJECT
    ( 
     SUBJECT_ID NUMBER (10), 
     FNAME VARCHAR2(30)  not null, 
     LNAME VARCHAR2(30)  not null, 
     EMAILADR VARCHAR2 (40),
     BIRTHDT  DATE       not null,
     constraint pk_sub primary key(subject_id) USING INDEX TABLESPACE data_index
    ) 
;

при вставке нового объекта, sub_seq используется для создания идентификатора объекта, определение здесь

create sequence sub_seq
       MINVALUE 1 
       MAXVALUE 999999999999999999999999999 
       START WITH 1
       INCREMENT BY 1 
       CACHE 100 
       NOCYCLE ;

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

@Entity
@Table(name="ktbs.syn_subject")
public class Subject {

    @Id 
    @Column(name="subject_id")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ")
    @SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ")
    private long subjectId;
    private String fname;
    private String lname;
    private String emailadr;
    private Date birthdt;
}

в тематической таблице было 4555 объектов в базе данных, загружаемых скриптами plsql из excel, и sub_sequence работала нормально. Идентификаторы объектов варьируются от 1 до 4555.

однако, когда я добавил тему из моего приложения, используя спящий режим, номер последовательности подскочил до 255050. После нескольких дней работы объекты ids, сгенерированные спящим режимом, выглядят следующим образом:

270079
270078
270077
270076
270075
270074
270073
270072
270071
270070
270069
270068
270067
270066
270065
270064
270063
270062
270061
270060
270059
270058
270057
270056
270055
270054
270053
270052
270051
270050
265057
265056
265055
265054
265053
265052
265051
265050
260059
260058
260057
260056
260055
260054
260053
260052
260051
260050
255067
255066
255065
255064
255063
255062
255061
255060
255059
255058
255057
255056
255055
255054
255053
255052
255051
255050
4555
4554
4553
.
.
.
.
1

Существует несколько больших разрывов: от 4555 до 255051, от 255067 до 260051, от 265057 до 270051.

Это отходы, а не желаемое поведение.

кто-нибудь знает, почему это происходит, и жарко, чтобы исправить его.

Спасибо

Ответ 1

Я думаю, что проблема связана с тем, что генератор последовательности не является генератором последовательности, а генератором последовательности hilo с размером распределения по умолчанию 50. Как указано в документации: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-identifier

Это означает, что если значение последовательности равно 5000, следующее сгенерированное значение будет 5000 * 50 = 250000. Добавьте значение кэша последовательности в уравнение, и это может объяснить ваш огромный начальный разрыв.

Проверьте значение последовательности. Он должен быть меньше, чем последний сгенерированный идентификатор. Будьте осторожны, чтобы не повторно инициализировать последовательность до этого последнего сгенерированного значения + 1, потому что сгенерированный valus будет экспоненциально расти (у нас была эта проблема и имела отрицательные целые идентификаторы из-за переполнения)

Ответ 2

Согласитесь с JB. Но все же благодаря PaulJ.

Чтобы быть более конкретным для моего аннотационного кода ниже:

@Entity
@Table(name="ktbs.syn_subject")
public class Subject {

  @Id 
  @Column(name="subject_id")
  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ")
  @javax.persistence.SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ")
  private long subjectId;
  private String fname;
  private String lname;
  private String emailadr;
  private Date birthdt;
}

Если вы используете javax.persistence.SequenceGenerator, hibernate использует hilo и, возможно, создаст большие пробелы в последовательности. Существует пост, посвященный этой проблеме: https://forum.hibernate.org/viewtopic.php?t=973682

Есть два способа исправить эту проблему.

  • В аннотации SequenceGenerator добавьте allocationSize = 1, initialValue= 1
  • вместо использования javax.persistence.SequenceGenerator, используйте org.hibernate.annotations, например:

    @javax.persistence.SequenceGenerator(
        name = "Question_id_sequence", 
        sequenceName = "S_QUESTION"
    )
    
    @org.hibernate.annotations.GenericGenerator(
        name="Question_id_sequence", 
        strategy = "sequence", 
        parameters = { 
            @Parameter(name="sequence", value="S_QUESTION") 
        }
    )
    

Я тестировал оба способа, который работает отлично.

Ответ 3

Другое решение:

Используйте 'strategy = GenerationType.AUTO' вместо 'strategy = GenerationType.SEQUENCE', как показано ниже

@Id
@SequenceGenerator(name = "studentId", sequenceName = "student_Id")
@GeneratedValue(strategy = GenerationType.AUTO, generator="studentId")  
private int studentId;

Ответ 4

Если вы прочтете следующую ссылку, вы увидите, что проблема вызвана установкой CACHE в команде создания последовательности. Удаление настройки кеша решит проблему до некоторой степени - но не учитывает возможности откатов и т.д.

Ссылка: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:369390500346406705

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

ПРИМЕЧАНИЕ. Значение кеша для последовательностей полезно для больших нагрузок, где значения последовательности "x" выделяются сразу. Если вы используете транзакционную систему, в которую вы вставляете один раз, то кеширование не является полезным (или я должен сказать - я никогда не считал его полезным).

ПРИМЕЧАНИЕ. Это мое понимание опции кеша для последовательностей. Для получения дополнительной информации вы можете найти документацию Oracle для команд CREATE SEQUENCE. Но ссылка выше должна дать разумный ответ на ваш вопрос.

Спасибо. Пол

Ответ 5

Фактически наличие allocSize = 1 является прекрасным, если ваша последовательность INCREMENT VALUE равна 1, и вам не нужно сохранять много объектов. Однако, если вы хотите сохранить тысячи или миллионы записей, приведенный выше параметр может стать узким местом производительности, поскольку для каждого сохранения необходимо получить идентификатор, поэтому ему нужно прочитать db.

Чтобы решить эту проблему, нам нужно установить allocationSize примерно на 500 и последовательность INCREMENT VALUE в БД также на 500, тогда самое важное добавить настройку спящего режима hibernate.id.new_generator_mappings, чтобы попросить его использовать генератор новой последовательности реализация, здесь я предполагаю, что вы задали свои свойства спящего режима в классе конфигурации Java:

properties.setProperty("hibernate.id.new_generator_mappings", Boolean.toString(true));

Таким образом, Hibernate будет использовать SequenceStyleGenerator вместо старого SequenceHiLoGenerator для создания идентификаторов. SequenceStyleGenerator больше подходит для jpa и oracle. Он генерирует значения идентификатора на основе структуры базы данных в стиле последовательности. Вариации варьируются от фактического использования последовательности до использования таблицы для имитации последовательности.

Посмотрите мое сообщение для более подробной информации, если вы находитесь в одной лодке:

vcfvct.wordpress.com/2016/04/23/jpa-sequencegenerator-with-allocationsize-1-performance-tuning/

Ответ 6

Самый успешный ответ:

@Id
@SequenceGenerator (name = "id_sequence", sequenceName = "sq50")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "id_sequence")
public int getId() {
return id;
}

Ответ 7

У меня были похожие проблемы. генератор последовательности и генератор hilo последовательности весьма схожи, но имеют различия. В hibernate 3 генератор hilo умножается на значение по умолчанию 50. Поэтому нет необходимости увеличивать последовательность DB. С другой стороны, более поздние версии hibernate используют генератор последовательностей по умолчанию. Поэтому требуется увеличение DB на 50.

https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.3/html/Migration_Guide/Preserve_the_Existing_Behavior_of_the_Hibernate_Identity_Auto_Generated_Value1.html

У меня была эта проблема с несколькими версиями спящего режима (3 и 5). Такая же конфигурация работала нормально (увеличивается на 1 в БД). Но не удалось спящий режим 5. Поэтому я обновляю свой persistence.xml, как показано ниже. Это обеспечивает hilo поколение

        <property name="hibernate.id.new_generator_mappings" value="false" />

Ответ 8

Как сказано здесь, попробуйте настроить SequenceGenerator.allocationSize с номером вашей базы данных INCREMENT BY.