SQL テーブルを構造化して一致するようにするか、結果を返さないようにするのが良いでしょうか。

StackOverflow https://stackoverflow.com/questions/23399

  •  09-06-2019
  •  | 
  •  

質問

興味深いデザインの質問があります。私はプロジェクトのセキュリティ面を設計しており、さまざまなコストでさまざまなバージョンのプログラムを使用できるようにするとともに、管理者タイプのユーザーがプログラムの一部へのアクセスを他のユーザーに許可または拒否できるようにします。これは Web ベースになり、当社のサーバーでホストされるようになります。

「リソース」または画面ごとに単純な許可または拒否オプションを使用しています。

多数のリソースがあり、ユーザーはアクセスを制御するためにユーザーを配置するさまざまなグループをセットアップできるようになります。各ユーザーは 1 つのグループにのみ所属できます。

私はこれに対して 2 つのアプローチを念頭に置いており、どちらが SQL サーバーにとってパフォーマンスの点で優れているのか興味がありました。

オプションAアクセス テーブルにエントリが存在するということは、アクセスが許可されていることを意味します。これにより、データベースに情報を保存するための列が必要なくなります。結果が返されない場合、アクセスは拒否されます。

これはテーブルが小さいことを意味すると思いますが、クエリはテーブル全体を検索して、一致するものがないと判断するのでしょうか?

オプション Bデータベースには許可/拒否を制御するビット列が含まれています。これは、常に結果が見つかることを意味し、テーブルが大きくなります。

考えは?

役に立ちましたか?

解決

許可/拒否だけを行う場合は、ユーザーとリソース間の単純なリンク テーブルで問題なく機能します。リンク テーブルに User-Resource にキー設定されたエントリがある場合は、アクセスを許可します。

UserResources
-------------
UserId FK->Users
ResourceId FK->Resources

SQLは次のようになります

if exists (select 1 from UserResources 
where UserId = @uid and ResourceId=@rid)
set @allow=1;

(UserId と ResourceId) にクラスター化インデックスを使用すると、数百万のレコードがあってもクエリが驚くほど高速になります。

他のヒント

私は選択肢 B に投票します。オプション A を使用し、ユーザーが存在すれば侵入できるという前提をとった場合、最終的にはユーザー レコードを削除せずにユーザーへのアクセスを拒否する必要があるという問題に遭遇します。

ユーザーをロックアウトしたいが、アカウントを完全に破棄したくない場合は数多くあります。そのような例の 1 つは (必ずしもあなたのユースケースに関連しているわけではありません)、支払いを怠った場合、再度支払いを開始するまでアカウントが遮断される場合です。彼らは、アカウントを最初から再作成してすべてのユーザー履歴を失うのではなく、再度支払うときにレコードを有効にしたいため、レコードを削除したくありません。

B.これにより、データが完全であるかどうかをより適切にチェックできるようになります (たとえば、許可/拒否可能な機能を追加する場合)。

また、テーブル サイズは、多くのレコード (100,000 以上など) が含まれることがわかっているテーブルについてのみ考慮する必要があります。この質問にテーブル サイズの考慮事項を入力するのに時間を費やしただけでも、必要となる追加のハード ドライブ スペースよりも多くのコストがかかります。

アプローチ A ですが、暗黙的な拒否に加えて明示的な拒否も含めます。最終ロジックが確実に機能するようにいくつかのユースケースを作成しますが、ここではいくつかの例を示します。

User1 is in group1 and group2.  
User2 is in group1  
User3 is in group2 

Folder1 allows group1 and deny group2.  
User1 is denied.  
User2 is allowed.  
User3 is denied. 

あなたのアプローチ users1 は許可されると思います。

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