質問

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

たとえば、人のリストがあるとします。

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

つまり、アクティブな人々のリストを取得するには、次のようにする必要があります。

SELECT * FROM people WHERE active=True;

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

好奇心が刺激される...

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

ありがとう

役に立ちましたか?

解決

アクティブなレコードが 1 つのパーティションに存在し、非アクティブなレコードがもう 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 でパーティション テーブルを作成する例を提供しました。

他のヒント

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

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

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

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

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

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

アクティブフラグは少々見苦しいですが、シンプルでうまく機能します。

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

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

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

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

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

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

SELECT count(*) FROM users WHERE active=1

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

ALTER TABLE users ADD INDEX index_users_on_active (active)

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

スキーマに役立つフラグを設定する前に、そのデータにアクセスする方法を検討してください。

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

私たちはアクティブフラグを頻繁に使用します。ただし、データベースが非常に大規模になる場合は、非アクティブな値を別のテーブルに移行することに価値があることがわかります。

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

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

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

ほとんどの場合、一度埋められると戻らず、概要/レポートなどにのみ使用される場合、メイン テーブルが小さくなり、クエリが単純になり、おそらく高速になります。

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

データが不要になり、データがリレーションの一部ではない場合、「分離テーブルに移動」メソッドを使用します。

解決策は状況によって決まります、私は次のように考えています。

テーブルにユーザーが含まれている場合は、複数の「フラグ」フィールドを使用できます。1 つは削除済み、無効化などです。または、スペースが問題になる場合は、無効のフラグを設定し、行が削除されている場合は実際に行を削除するだけで十分です。

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

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

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

2) もちろん、レコードを完全に削除するオプションはまだ存在します。ただし、私たち開発者はデータパック狂いの傾向がありますが、ビジネスプロセスを見て、データを保持する必要があるかどうかを判断することをお勧めします。あります - そうしてください...そうでない場合は、おそらく、特定のビジネス シナリオに従って、そのものを自由に捨てるべきです。

「純粋主義的な観点」から見ると、現実モデルはビューとテーブルを区別せず、どちらもリレーションです。そのため、エンティティの名前が正しく指定されていれば、識別子を使用するビューの使用は完全に意味があり、有効です。人物/アクティブな人。

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

ブール値のインデックス作成については、次のようにしてみてはいかがでしょうか。

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top