web-dev-qa-db-ja.com

休止状態のOracleシーケンスにより大きなギャップが生じる

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を使用してサブジェクトIDが作成されます。定義はここにあります

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;
}

subjectテーブルでは、Excelからplsqlスクリプトによってロードされたデータベースに4555件のサブジェクトがあり、sub_sequenceは正常に機能しました。サブジェクトIDの範囲は1〜4555です。

ただし、Hibernateを使用してアプリケーションからサブジェクトを追加すると、シーケンス番号が255050にジャンプしました。数日実行すると、Hibernateによって生成されたサブジェクトIDは次のようになります。

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

これは無駄であり、望ましい動作ではありません。

誰がこれが起こるのかを知っていて、それを修正するのが熱い

ありがとう

32
sse

問題は、シーケンスジェネレーターが実際にはシーケンスジェネレーターではなく、デフォルトの割り当てサイズが50のシーケンスヒロジェネレーターであるという事実に起因すると考えます。ドキュメントに示されているように、 http://docs.jboss。 org/hibernate/stable/annotations/reference/en/html_single /#entity-mapping-identifier

これは、シーケンス値が5000の場合、次に生成される値は5000 * 50 = 250000になることを意味します。シーケンスのキャッシュ値を式に追加すると、初期ギャップが大きくなる可能性があります。

シーケンスの値を確認してください。最後に生成された識別子よりも小さくする必要があります。生成された値は指数関数的に増加するため、シーケンスをこの最後に生成された値+ 1に再初期化しないように注意してください(この問題があり、オーバーフローのために負の整数IDがありました)

42
JB Nizet

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を使用する場合、休止状態はhiloを使用し、シーケンスに大きなギャップを作成する可能性があります。この問題に対処する投稿があります: https://forum.hibernate.org/viewtopic.php?t=973682

この問題を解決するには2つの方法があります

  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") 
        }
    )
    

私は両方の方法をテストしましたが、うまくいきます。

37
sse

別の解決策は次のとおりです。

以下のように、@GeneratedValueの戦略として 'GenerationType.SEQUENCE'の代わりに 'GenerationType.AUTO'を使用します。

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

シーケンスINCREMENT VALUEが1で、多くのエンティティを永続化する必要がない場合は、実際にallocationSize = 1で十分です。ただし、数千または数百万件のレコードを永続化する場合、上記の設定はパフォーマンスボトルネックになる可能性があります。これは、保存するたびにIDを取得する必要があるため、dbの読み取りが必要になるためです。

この問題を解決するには、allocationSizeを500のように設定し、DBのシーケンスINCREMENT VALUEも500に設定する必要があります。次に、最も重要なのは使用するようにhibernate.id.new_generator_mappings休止状態設定を追加することです新しいシーケンスジェネレーターの実装。ここでは、Java Configクラスでhibernateプロパティを設定すると仮定します。

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

このように、Hibernateは古いSequenceStyleGeneratorではなくSequenceHiLoGeneratorを使用してIDを生成します。 SequenceStyleGeneratorは、jpaおよびOracleにより適しています。シーケンススタイルのデータベース構造に基づいて識別子の値を生成します。バリエーションは、実際にシーケンスを使用することから、テーブルを使用してシーケンスを模倣することまでさまざまです。

同じボートに乗っている場合は、私の投稿で詳細を確認してください。

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

6
LeOn - Han Li

次のリンクを読むと、シーケンス作成コマンドのCACHE設定が問題の原因であることがわかります。キャッシュ設定を削除すると、問題はある程度解決されますが、ロールバックなどの可能性は考慮されません。

リンク: http://asktom.Oracle.com/pls/apex/f?p=100:11:0:::::P11_QUESTION_ID:369390500346406705

シーケンスを再同期する唯一の方法は、シーケンスを再作成し、現在のテーブルの名前を変更してテーブルを再度作成してから、古いテーブルから新しいテーブルにレコードを再挿入することです。

注:シーケンスのキャッシュ値は、「x」シーケンス値が一度に割り当てられる大規模な負荷に役立ちます。一度に1つの挿入を行うトランザクションシステムを使用している場合、キャッシュは役に立ちません(または言うべきです-役に立たなかった)。

注:これは、シーケンスのキャッシュオプションに関する私の理解です。詳細については、CREATE SEQUENCEコマンドに関するOracleドキュメントを参照してください。しかし、上記のリンクはあなたの質問に対する合理的な答えを提供するはずです。

ありがとう。ポール

5
PaulJ

これに対する解決策の1つとして、allocationSizeを使用してシーケンスジェネレーターを構成できます。

@SequenceGenerator(name = "gen_name", sequenceName = "seq_name", allocationSize= 1)
2

同様の問題がありました。シーケンスジェネレーターとシーケンスヒロジェネレーターは非常に似ていますが、違いがあります。 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)があるこの問題がありました。同じ構成が正常に機能しました(DBで1ずつ増加)。しかし、休止状態5で失敗しました。したがって、persistence.xmlを以下のように更新します。これにより、ヒロの生成が保証されます

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

最も成功した答えは次のとおりです。

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

here のように、SequenceGenerator.allocationSizeデータベースシーケンスINCREMENT BY番号。

0
Anthony O.