Спящая последовательность оракула дает большой разрыв - PullRequest
30 голосов
/ 18 марта 2011

Я использую 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 ;

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

@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, и подпоследовательность работала нормально.Идентификаторы субъекта варьируются от 1 до 4555.

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

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

это пустая трата и нежелательное поведение.

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

Спасибо

Ответы [ 9 ]

40 голосов
/ 18 марта 2011

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

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

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

36 голосов
/ 18 марта 2011

Согласен с 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

Есть два способа решения этой проблемы

  1. В аннотации SequenceGenerator добавьте allocationSize = 1, initialValue= 1
  2. вместо использования 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") 
        }
    )
    

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

6 голосов
/ 24 апреля 2016

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

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

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

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

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

vcfvct.wordpress.com / 2016/04/23 / JPA-sequencegenerator-с-allocationsize-1-настройки производительности /

6 голосов
/ 22 ноября 2012

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

Используйте «GenerationType.AUTO» вместо «GenerationType.SEQUENCE» в качестве стратегии для @GeneratedValue, как показано ниже;

@Id
@SequenceGenerator(name = "studentId", sequenceName = "student_Id")
@GeneratedValue(strategy = GenerationType.AUTO, generator="studentId")  
private int studentId;
5 голосов
/ 18 марта 2011

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

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

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

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

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

Спасибо.Пол

2 голосов
/ 30 августа 2018

В качестве одного из решений мы можем настроить генератор последовательностей с allocSize как:

@SequenceGenerator(name = "gen_name", sequenceName = "seq_name", allocationSize= 1)
1 голос
/ 05 мая 2016

У меня были похожие проблемы. генератор последовательности и генератор последовательности очень похожи, но имеют различия. В hibernate 3 генератор hilo умножается на значение по умолчанию 50. Поэтому нет необходимости увеличивать последовательность DB. С другой стороны, в более поздних версиях hibernate по умолчанию используется генератор последовательностей. Поэтому требуется увеличение БД на 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 в БД). Но не удалось в hibernate 5. Поэтому я обновляю свой файл persistence.xml, как показано ниже. Это гарантирует поколение hilo

        <property name="hibernate.id.new_generator_mappings" value="false" />
1 голос
/ 23 мая 2013

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

@Id
@SequenceGenerator (name = "id_sequence", sequenceName = "sq50")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "id_sequence")
public int getId() {
return id;
}
0 голосов
/ 05 февраля 2015

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...