23

OK、つまり、事実上すべてのデータベースベースのアプリケーションは「非アクティブ」レコードを処理する必要があります。ソフト削除するか、何かを「無視する」とマークします。「アクティブ」列(またはステータス列)に根本的な代替案があるかどうかについて興味があります。

たとえば、私が人々のリストを持っていた場合

CREATE TABLE people (
  id       INTEGER PRIMARY KEY,
  name     VARCHAR(100),
  active   BOOLEAN,
  ...
);

つまり、アクティブな人のリストを取得するには、を使用する必要があります

SELECT * FROM people WHERE active=True;

非アクティブなレコードを別のテーブルに移動し、2つを結合するために適切なUNIONが実行されることを提案する人はいますか?

好奇心が印象的...

編集: 私は明確にする必要があります、私は純粋主義者の観点からこれに来ています。大量のデータに対してデータアーカイブがどのように必要になるかはわかりますが、それは私がどこから来たのかではありません。SELECT * FROMの人々を行う場合、それらのエントリはある意味で「アクティブ」であることが私には理にかなっています。

ありがとう

4

18 に答える 18

23

アクティブ フラグに基づいてテーブルを分割し、アクティブなレコードが 1 つのパーティションにあり、非アクティブなレコードが別のパーティションにあるようにします。次に、自動的にアクティブ フィルターを持つ各テーブルのアクティブ ビューを作成します。データベース クエリ エンジンは、アクティブなレコードを含むパーティションにクエリを自動的に制限します。これは、そのフラグでインデックスを使用するよりもはるかに高速です。

これは、Oracle で分割されたテーブルを作成する方法の例です。Oracle にはブール列型がないため、Oracle 用にテーブル構造を変更しました。

CREATE TABLE people
(
   id       NUMBER(10),
   name     VARCHAR2(100),
   active   NUMBER(1)
)
PARTITION BY LIST(active)
(
   PARTITION active_records VALUES (0)
   PARTITION inactive_records VALUES (1)
);

必要に応じて、各パーティションを異なるテーブルスペースに配置できます。インデックスを分割することもできます。

ちなみに、これはこの質問の繰り返しのようです。初心者として、意図しない重複を処理する手順は何ですか?

編集:コメントで要求されたように、Oracleでパーティション分割されたテーブルを作成する例を提供しました

于 2008-09-19T14:36:08.290 に答える
8

ほとんどの状況でアクティブレコードのみを描画するようにするには、アクティブレコードのみを含むビューを作成できます。そうすれば、アクティブな部分を省略しない方がはるかに簡単です。

于 2008-09-19T14:32:22.853 に答える
3

ほとんどのテーブルで enum('ACTIVE','INACTIVE','DELETED') を使用しているため、実際には 3 方向のフラグがあります。さまざまな状況でうまく機能することがわかりました。あなたのマイレージは異なる場合があります。

于 2008-09-19T14:55:03.453 に答える
3

非アクティブなものを移動することは、通常、ばかげた考えです。バグが発生する可能性があり、多くのオーバーヘッドがあり、アーカイブを解除するなど、すべてがより複雑になります。関連するデータはどうしますか? それもすべて移動すると、すべてのクエリを変更する必要があります。それを動かさない場合、どのような利点が得られることを望んでいましたか?

それは次のポイントにつながります。なぜそれを動かしますか? 適切にインデックスが作成されたテーブルでは、サイズが 2 倍になると、追加のルックアップが 1 回必要になります。パフォーマンスの向上は無視できるものです。そして、実際にパフォーマンスの問題が発生する遠い将来まで、なぜそれについて考えるのでしょうか?

于 2008-09-19T14:55:15.560 に答える
2

厳密にデータとして見ると、元の投稿に示されている方法が適切であると思います。データのアクティブ フラグ部分は、主キーに直接依存しており、テーブルに存在する必要があります。

そのテーブルには、データの現在のステータスに関係なく、人々に関するデータが保持されます。

于 2008-09-19T14:57:15.103 に答える
1

スキーマでこのようなバイナリ フラグを使用することは、悪い考えです。クエリを検討する

SELECT count(*) FROM users WHERE active=1

シンプルに見えます。しかし、ユーザー数が非常に多く、このテーブルにインデックスを追加する必要がある場合はどうなるでしょうか。繰り返しますが、それはまっすぐに見えます

ALTER TABLE users ADD INDEX index_users_on_active (アクティブ)

を除外する!!この列のカーディナリティはちょうど 2 であるため、このインデックスは役に立ちません。このインデックスはカーディナリティが低いため、データベース クエリ オプティマイザは無視し、テーブル スキャンを実行します。

有用なフラグでスキーマを埋める前に、そのデータにアクセスする方法を検討してください。

https://stackoverflow.com/questions/108503/mysql-advisable-number-of-rows

于 2008-09-21T13:41:01.260 に答える
1

アクティブ フラグはちょっと見にくいですが、シンプルでうまく機能します。

あなたが提案したように、それらを別のテーブルに移動できます。アクティブ/非アクティブなレコードの割合を確認することをお勧めします。非アクティブなレコードが 20% または 30% を超える場合は、それらを別の場所に移動することを検討してください。そうでなければ、それは大したことではありません。

于 2008-09-19T14:32:37.737 に答える
1

はい、そうします。現在、主に「最新」の行を表示するために、多くのテーブルに「active='T/F'」列があります。新しい行が挿入されると、前の T 行は F とマークされ、監査目的で保持されます。

現在、2 テーブル アプローチに移行しています。新しい行が挿入されると、前の行が履歴テーブルに移動されます。これにより、現在のデータを見ると、ほとんどの場合でパフォーマンスが向上します。

以前は更新と挿入が必要でしたが、現在は挿入と更新が必要です (つまり、新しい T 行を挿入する代わりに、すべての新しいデータで既存の行を変更します)。変更だけを渡すのではなく、データの行全体を渡すだけです。それではほとんど効果が出ません。

パフォーマンス上の利点は、メイン テーブルのインデックスが大幅に小さくなり、テーブルスペースをより適切に最適化できることです (テーブルスペースはそれほど大きくなりません!)。

于 2008-09-19T14:35:55.840 に答える
0

アクティブフラグを頻繁に使用します。ただし、データベースが非常に大きくなる場合は、非アクティブな値を別のテーブルに移行することの価値を確認できます。

その場合、誰かがアクティブまたは非アクティブのすべてのレコードを表示したい場合にのみ、テーブルの結合が必要になります。

于 2008-09-19T14:32:15.757 に答える
0

「純粋主義者の観点」から見ると、現実モデルはビューとテーブルを区別しません。どちらも関係です。そのため、識別子を使用するビューの使用は完全に意味があり、エンティティが Person/ActivePerson などのように正しく名前が付けられていれば有効です。

また、「純粋主義者の観点」から、リレーションの名前はセット全体ではなくタプルを反映するため、テーブルには people ではなく person という名前を付ける必要があります。

于 2008-09-19T16:49:49.623 に答える
0

いいえ-これはかなり一般的なことです-特定の要件に応じていくつかのバリエーションがあります(ただし、すでに説明しました):

1) 数テラバイト以上のような大量のデータがあると予想される場合、削除されたレコードをすぐにアーカイブすることは悪い考えではありませんが、削除済みとしてマークしてからアーカイブ テーブルにコピーするという組み合わせのアプローチを使用することもできます。

2) もちろん、レコードをハード削除するオプションはまだ存在します - 私たち開発者はデータパックラットになる傾向があります - ビジネスプロセスを見て、データを保持する必要があるかどうかを判断することをお勧めします -あります - そうしてください... ない場合は、特定のビジネスシナリオに応じて、単に物を捨てるだけで構いません....もう一度言います。

于 2008-09-19T14:42:35.590 に答える
0

非アクティブなレコードを処理するために両方の方法を使用します。私たちが使用する方法は、状況によって異なります。基本的にルックアップ値であるレコードの場合、アクティブ ビット フィールドを使用します。これにより、エントリを非アクティブ化して使用されないようにすることができますが、リレーションとのデータの整合性を維持することもできます。

データが不要になり、データが関係の一部でなくなった場合は、「分離テーブルに移動」メソッドを使用します。

于 2008-09-19T14:37:56.490 に答える
0

状況が実際に解決策を決定する、と私は考えます:

テーブルにユーザーが含まれている場合、いくつかの「フラグ」フィールドを使用できます。Deleted、Disabled などの 1 つ。または、スペースが問題である場合は、disabled のフラグで十分であり、行が削除されている場合は実際に行を削除します。

また、データを保存するためのポリシーにも依存します。データをアーカイブしておくためのポリシーがある場合、かなりの時間が経過した後で別のテーブルが必要になる可能性が高くなります。

于 2008-09-19T14:39:57.673 に答える
0

ほとんどの場合、削除を示すバイナリ フィールドで十分です。多くの場合、一定時間後に削除されたレコードを削除するクリーンアップ メカニズムがあるため、削除されたタイムスタンプでスキーマを開始したい場合があります。

于 2008-09-19T14:33:12.570 に答える
0

別のテーブルに移動して元に戻すには時間がかかります。オフラインになるレコードの数と、それらを戻す必要がある頻度に応じて、それが良いアイデアである場合とそうでない場合があります。

それらが埋もれ、要約/レポートなどにのみ使用されると、ほとんどが戻ってこない場合、メインテーブルが小さくなり、クエリがより簡単になり、おそらく高速になります。

于 2008-09-19T14:33:46.640 に答える
0

ブール値のインデックス付けに関して、なぜですか:

ALTER TABLE users ADD INDEX index_users_on_active (id, active) ;  

それは検索を改善しませんか?
ただし、その答えがプラットフォームにどの程度依存するかはわかりません。

于 2011-02-17T19:47:14.857 に答える
0

大きなテーブルのビット フラグでデータをフィルタリングすることは、パフォーマンスの点であまり良くありません。「アクティブ」が仮想削除を決定する場合、同じ構造を持つ「TableName_delted」テーブルを作成し、削除トリガーを使用して削除されたデータをそこに移動できます。

このソリューションは、パフォーマンスを向上させ、データ クエリを簡素化します。

于 2020-02-03T21:42:10.703 に答える