2012-04-04 10 views
2

JPAまたはデータベース・レベルのいずれかで、データベース表の主キーにMAX値を設定できますか?それが不可能な場合は、私は約データベーステーブルの主キーにMAX値を設定できますか?

  1. が戻りオブジェクトがある場合は、新たに、keyを作成してデータベース上でSELECTを実行してください
  2. (9999999999私のMAXである)0から9999999999の間のランダムな keyを作成します考えていました null、INSERT、繰り返していない場合は、手順1に戻ります。

したがって、私は上記の2つの質問を行います。環境が同時に高いことに注意してください:

Q1:SELECTでチェックするオーバーヘッドはありますか?INSERTは重要ですか?私が本当に意味するのは、通常、このプロセスは普通です、なぜなら私はDBが私のために一意のPKを作成させるからです。

質問2:Q1でパフォーマンスが大幅に低下しない場合は、同時に問題に対処できますか?たとえば、Id1のP1がテーブルをチェックしていれば、Id1はそこにはなく、挿入する準備ができています.P2がP1の前に挿入Id1に潜んでいます。したがって、P1がId1を挿入すると失敗します。私はここでプロセスが失敗するのを望んでいない、私はそれがループをバックアップする、新しいIDを見つける、プロセスを繰り返すしたい。それ、どうやったら出来るの?

私の環境はSQLとMYSQLです。私はEclipseLinkを実装

NOTEでJPAを使用します。一部の人々はこのようにそれを実装するために私の決定を疑問視、答えはTravisJは以下示唆するもの正確です。私は非常に高い並行環境を持っています。プロセスが始動すると、別のプロセスへのリクエストを作成し、そのプロセスに固有の10文字のIDを渡す必要があります。環境は大電流であるため、PKのユニークで非ヌルな機能を活用したいと考えています。リクエストには大量の情報が含まれているので、リクエストIDが自分のPKであるRequestテーブルを作成します。私は、すべてのDBのインデックスは、PKのクエリは、PKのクエリが速いので知っている。より良い方法があれば教えてください。

+3

なぜこのようなことをしたいですか? – Ben

+1

あなたがそれを望む理由は事実上存在しません。 PKの役割を酷使しているように見えますが、これはあなたが何か間違っていることを示しています。長い話は短いです:それをしないでください。 –

+1

私は理由がないという意見に同意します。これは、主キーのための何らかの種類のハッシュを作成するために使用できます。育った主な問題は競合状態であるように見えます。これは、異なるプロセスがセマフォを必要とすることを意味します。 –

答えて

2

あなたのテーブル定義にCHECK制約を実装できます。

CREATE TABLE P 
(
P_Id int PRIMARY KEY NOT NULL, 
... 
CONSTRAINT chk_P_Id CHECK (P_Id>0 and P_Id<9999999999) 
) 

EDIT:コメントで述べたように、MySQLはCHECK制約を尊重しません。これはバグログの6年前の不具合であり、MySqlチームはまだそれを修正していません。 MySqlは現在、Oracle Corpによって監督されているため、修正されることはありません(単純に「文書化された制限」とみなされ、好きでない人は有料のDBMSにアップグレードできます)。ただし、この構文およびチェック制約機能自体は、Oracle、MS SQL Server(SQLExpress/MSDEを含む)、MS Access、PostgreおよびSQLiteで動作します。

+0

すべてのデータベースで動作しますか? –

+1

この構文は、MySql、Oracle、MSS、およびMS Accessで確実に機能します。 http://www.w3schools.com/sql/sql_check.asp ALTER TABLEの関連する構文は、それらのすべてのDBでも有効です。私はSQLiteやPostgreSQLについて話すことができません。 – KeithS

+1

制約をチェックする[_doはMySQLで動作しません](http://stackoverflow.com/questions/2115497/check-constraint-in-mysql-not-working)。彼らは静かに失敗する。 – Ben

2

なぜ1で始まり、自動インクリメントを使用しないのですか?これは、衝突を起こさないため、サイクルを繰り返す必要があるため、ずっと効率的です。数字が足りなくなったら、同じボートに乗ることになりますが、少なくとも連続して行くと、衝突に対処する必要はありません。

利用可能な番号の90%を使い切ったときに、未使用のキーを見つけようとしているとします。これには時間がかかりますが、ランダムに生成する場合は、(生涯で)未使用の鍵が見つからない可能性が常にあります。

また、自動インクリメントを使用すると、限界に近いかどうかを簡単に確認できます(SELECT MAX(col))。リセットする必要があるときにアラートをスクリプト化して通知することができます。ランダムメソッドの場合、そのクエリはどのように見えますか?

InnoDBを使用している場合でも、主キーを使用したくない場合があります。実際の表データを並べ替える必要があるため、クラスタ化された索引にランダムなレコードを挿入するとパフォーマンスが低下します。代わりに、ユニークキー(自動インクリメントプライマリキー付き)を使用します。

問題の列に一意のインデックスを使用すると、範囲内の乱数を生成して挿入するだけです。挿入が失敗した場合は、新しい番号を生成して再試行してください。挿入が成功した場合は、処理を続行します。これは並行性の問題を説明します。

しかし、順次自動インクリメントキーは、より優れたパフォーマンスを実現します。

+0

3ヶ月ごとにデータベースのクリーンアップを行う予定です。キーはデータベースから削除されます。したがって、自動インクリメントキーでは、データベースキーはラップアラウンドしますが、MAX(9999999999)ですが、0〜50000000のキーはデータベースを削除してから解放されています。次の挿入のためにキーを回しますか? –

+0

@ThangPham、データベースを消去した後に再び1の自動インクリメント列を開始するには、単に 'ALTER TABLE tbl AUTO_INCREMENT = 1'を実行します。 –

1

を参照してください、

http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing

と、

http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Advanced_Sequencing

JPAはすでに良いID生成をサポートしている、それはあなた自身を実装しても意味がありません。

並行性とパフォーマンスが懸念され、MySQLを使用している場合は、大きな事前割り当てサイズのTABLEジェネレータを使用することをお勧めします(他のデータベースではSEQUENCEジェネレータを推奨します)。大量のデータがある場合は、IDを長く使用するようにしてください。

本当にあなたがこれ以上必要と思うなら、UUID id生成を検討してください。 @UUIDGeneratorを提供するEclipseLink 2.4。

+0

これはまさに私が探しているものです。しかし、私はこれについて他の質問があります。私のデータベースはMicrosoft SQL Serverです。@ SequenceGeneratorをサポートしていないと思いますので、 '@ TableGenerator'を使用する必要があります。この記事を見れば、カップルの質問があります。http:// stackoverflow .com/questions/10033727/sequence-id-using-jpa-tablegenerator-generatの違いは何ですか?どうもありがとうございました –

関連する問題