5

私の現在の Rails アプリケーションでは、モデルを " created_at" フィールドでソートすることにより、スケジューリングの競合を解決しています。created_atしかし、これが可能なフォームから複数のモデルを挿入すると、すべての時間がまったく同じになることに気付きました。

これは、プログラミングのベスト プラクティスの問題です。アプリケーションは、データベース内の ID 列に依存してINSERT、作成順序を取得するたびに増加していくことができますか? 別の言い方をすれば、データベースから取り出した行のグループを ID 列で並べ替えて、これが作成順序に基づく正確な並べ替えであることを確認できますか? そして、これは私のアプリケーションで良い習慣ですか?

4

7 に答える 7

2

生成された識別番号は一意になります。PostgreSQL や Oracle のようにシーケンスを使用するかどうか、または MySQL の自動インクリメントのような別のメカニズムを使用するかどうかに関係なく。

ただし、シーケンスはほとんどの場合、たとえば 20 個の数字をまとめて取得します。したがって、PostgreSQL では、どのフィールドが最初に挿入されたかを判断できません。挿入されたレコードの ID にギャップが生じることさえあります。

したがって、データベース実装の詳細に依存しないために、そのようなタスクに生成された id フィールドを使用しないでください。

コマンドの実行中に作成または更新されたフィールドを生成すると、後で作成時間または更新時間でソートするのにはるかに適しています。例えば:

INSERT INTO A (data, created) VALUES (smething, DATE())
UPDATE A SET data=something, updated=DATE()
于 2009-05-10T14:21:52.023 に答える
1

これは、データベース ベンダーによって異なります。

MySQL 自動インクリメント キーは絶対に注文すると思います。SQL Server できるかどうかはわかりませんが、できると信じています。

問題が発生するのは、この機能をサポートしていないデータベース、特に大雑把ではあるが完全に順序付けられていないシーケンスを使用する Oracle です。

別の方法として、作成時間と ID を使用することもできます。

于 2009-05-10T14:12:54.783 に答える
0

EJBの回答に対する1つの注意点:

列ごとの順序を指定しない場合、SQLは順序を保証しません。たとえば、初期の行をいくつか削除してから'emを挿入すると、新しい行は、古い行が(新しいIDを使用していても)データベース内の同じ場所に存在することになり、デフォルトの並べ替えとして使用される可能性があります。

FWIW、私は通常、created_atによる注文の効果的なバージョンとしてIDによる注文を使用します。日時フィールドにインデックスを追加する必要がなく(単純な整数の主キーインデックスよりも大きいため遅い)、異なることが保証されているという点で安価です。ほぼ同時に追加され、わずかに異なる順序で並べ替えられます。

于 2009-05-10T15:08:29.310 に答える
0

あなたの質問への答えはイエスだと思います...行間を読むと、システムがシーケンスで「欠落している」ID番号を再利用する可能性があることを懸念していると思います。したがって、1を使用した場合、 ID番号として2、3、5、6、7、私が知っているすべての実装で、次のID番号は常に8(またはそれ以上)になりますが、試して理解しようとするDBは知りませんそのレコード ID #4 が欠落しているため、その ID 番号を再利用してみてください。

私は SQL Server に最も精通していますが、ベンダーがシーケンスのギャップを埋めようとする理由がわかりません。常に最新の ID を追跡するのではなく、未使用の ID のリストを保持するオーバーヘッドを考えてみてください。使用数、および 1 を追加します。

一意であるだけでなく、次の ID に割り当てられた番号が常に最後よりも大きいことに安全に依存できると思います。

于 2009-05-10T14:34:01.333 に答える
0

はい、ID は一意であり、いいえ、並べ替えに依存することはできませんし、依存すべきではありません。行の一意性のみを保証するためにあります。最善の方法は、emktas が示すように、この情報だけに別の「更新済み」または「作成済み」フィールドを使用することです。

作成時間を設定するには、このようなデフォルト値を使用できます

CREATE TABLE foo (
  id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL;
  created TIMESTAMP NOT NULL DEFAULT NOW();
  updated TIMESTAMP;
  PRIMARY KEY(id);
) engine=InnoDB; ## whatever :P

これで、作成時間が処理されます。更新時に、次のような AFTER UPDATE トリガーをお勧めします (もちろん、別のクエリで実行できますが、私の意見では、トリガーの方が優れたソリューションであり、より透過的です)。

DELIMITER $$
CREATE TRIGGER foo_a_upd AFTER UPDATE ON foo
FOR EACH ROW BEGIN
  SET NEW.updated = NOW();
END;
$$
DELIMITER ;

そして、それはそれを行う必要があります。

編集:私は悲惨です。ばかげて、これは mysql 用であることを指定していません。関数名 (つまり、「NOW」) やその他の微妙な違いにいくつかの違いがある可能性があります。

于 2009-05-10T14:38:46.780 に答える
0

これはおそらくDBエンジン依存です。DB がシーケンスをどのように実装しているかを確認し、文書化された問題がない場合は、ID に依存することにします。

たとえば、 Postgresql シーケンスは、シーケンス キャッシュ パラメータをいじらない限り問題ありません。

他のプログラマーが別の DB から間違った ID 列でレコードを手動で作成またはコピーする可能性があります。ただし、問題を単純化します。誰かが手動でデータの整合性を破壊する可能性が低いケースを気にしないでください。すべてを防御することはできません。

私のアドバイスは、シーケンスで生成された ID に依存して、プロジェクトを前進させることです。

于 2009-05-10T20:46:54.447 に答える
0

理論的には、最も高い ID 番号が最後に作成されたものです。ただし、データベースには、自動生成された値の挿入を一時的にオフにし、いくつかのレコードを手動で挿入してからオンに戻す機能があることに注意してください。これらの挿入は通常、本番システムでは使用されませんが、別のシステムから大量のデータを移動するときに時々発生する可能性があります。

于 2009-05-11T14:51:52.443 に答える