1

まず、お読みいただきありがとうございます。私が直面している問題を解決するためのアプローチのアイデアを持っています。それは、より適切に言えば要件です。以下に示すのは、現実のものではありませんが、機密情報を漏らさずに問題を表す架空のシナリオです。

ある国に住む人々の非常に大規模なデータベース、たとえば 1 億件のレコードを持つサービスを想像してみてください。

このサービスは、さまざまな企業がそれらの人々に関するデータを照会するために使用されています。通常のクエリは次のとおりです。

  • x 市に住んでいる 25 歳から 30 歳までのすべてのカトリック教徒を表示してください
  • 子供が 2 人以上いる人を表示
  • 年収10万~20万の人教えて
  • 昨年 3 回以上休暇を取った人を教えてください。

"People" (すごい..) という大きなテーブルがあり、1 億件のレコードすべてと、さまざまなフィールドに必要なすべての属性が含まれています。たとえば、40 列あるとしましょう (int、datetime、varchar、char などの組み合わせ.. ) 説明を取得したり、より複雑な属性を解決するためにメイン テーブルが参照する静的テーブル (25) も多数あります。

このデータベースを所有する会社は、Web サービスを介してこの DB にクエリを実行する機能を提供および販売しています。この Web サービスは、クエリ、クライアント ID、パラメータなどを受け取り、「できるだけ早く」結果セットを返す必要があります。

これまでのところ問題はありません。

このデータベースを所有する会社には、商用チームが管理する内部アプリケーションがあり、そこでは、各クライアントが x または y データにアクセスする機能を定義するさまざまなルールが設定されています。アクセスするデータが増えるほど、サービスに支払う金額も増えます。

すべてのクライアントがすべてを見ることができるわけではありません.一部のクライアントは特定の都市の人々のみを照会できます.他のクライアントは特定の年齢層の人々を見ることが許可されています,他のクライアントは特定の宗教「および」特定の社会経済レベルの人々など.

この DB を所有する会社は、毎日、必要に応じて上記のルールを変更し、クライアントがより多くまたはより少なく表​​示できるようにすることができます。所有者は、明日適用されるように今日変更することしかできません。同じ日やリアルタイムなどではありません。

したがって、この大きなデータベースは 1 つだけで、すべてのクライアントに対して、すべてのクライアントがあらゆる種類のクエリを作成しますが、システムは 2 つのレベルでデータを動的にフィルター処理する必要があります。

FIRST - 各クライアントが表示できるものを定義するビジネス ルールに基づく

SECOND - クエリのパラメーターに基づく (WHERE 句)

私の質問は、上記の「FIRST」動的フィルターを効率的に実装する方法です。

次のようないくつかのオプションがあります。

オプション 1 : クライアントごとにメイン テーブルのコピーを 1 つ用意し、1 日 1 回そのテーブルを切り捨て、メイン テーブルからレコードを再度挿入して、フィルタリング ルールをチェックし、クライアントが表示できるレコードのみを挿入します。このオプションは、クエリ パフォーマンスの観点からは優れていますが、処理時間の点では悪く、クライアントが増えると拡張性が低下します。テーブルと挿入が増え、処理時間が長くなります。そして、それは...醜いです..それは好きではありません.. :)

オプション 2 : ビジネス フィルタリング ルールを各リクエストの where 句に動的に追加します。大規模なバッチ プロセスを必要としないので良いですが、所有者がクライアントに対して定義できるフィルタリング ルールの数に制限がないため、where 句が長すぎる可能性があり、問題が発生する可能性があるため、好きではありません。 、およびフィルターは非常に複雑になる可能性があります(たとえば、会社Aは、70〜80歳で生まれ、ブロンドの髪を持ち、家族に1〜2台の車を持っている白人、「または」、黒人などにのみアクセスできます.. "または" bla bla.. "or" ) だから.. 要点はわかりますが、好きではありません。

オプション 3 : 私が考えていたのは、Row-Client などと呼ばれるテーブルを用意することです。これには、RowID とアクセスできるクライアントが含まれます。次に、ビジネス ルールに基づいてそのテーブルにデータを入力するバッチ プロセスが必要になります。(ただし、2 つの値しか挿入していないため、大きなプロセスではありません) 次に、クエリごとに、そのテーブルに結合を追加して、リクエストを実行している現在のクライアントに許可されている行のみを取得します。

次のようになります。

行: 1 クライアント: 1 行: 1 クライアント: 2

または(参照intはありません)

行: 1 クライアント: 1,2

または、その「クライアント」列をメイン テーブルに直接追加することもできます。

したがって、私の質問は、オプション 3 が機能するかどうか (1050 人のクライアントが営業時間について 1 日に 50 回クエリを実行する場合)、または効率的な方法でそれを達成するための他のアイデアや確立された方法、アプローチ、または技術を知ることです。

もちろん、私はあなたの質問/アイデアを受け入れており、あなたの助けに感謝しています.

クエリの実行後に結果セットからデータを削除することはできません。グループ化または集計操作が既に実行されているためです。

私が探しているのは、もちろんバッチ処理時間とクエリ応答時間を最小限に抑えることです。敬具

4

1 に答える 1

1

まず第一に、私はこれを実際に行った経験がないので、ここでは理論的です。私は、いかなる状況においても、あなたのピープルテーブルをどこでも繰り返すつもりはありません。クエリの結果をフィルタリングするために使用される別のクライアント制限ルール テーブルを保持します。

そのため、支払いをしていないデータであっても、必要なものに対してクエリを送信できますが、結果が返される前に、クエリ結果は、支払いを行った金額によって列や行を制限する別のプロセスを通過します。

OK、集約関数の行制限を考えると、2 つ (またはそれ以上) のステップのプロセスが必要になると思います。まず、行基準で制限してから、SQL を実行してから、列で制限します。スキーマを変更せずに将来作成される可能性のあるものによって制限する必要がある場合、行による制限は難しい部分です。最も簡単な方法は、制限できる行の基準を (ha,ha) 制限し、「isLimitedByAge」、「isLimitedByRace」などの名前の列を含む 1 つのテーブルを作成することです。

タイムラインによっては、今はあまり洗練されていないソリューションを使用して、これを分割して実装する必要がある場合があります。後で、ほとんどのクライアントがクエリを実行し、したがって支払いをいとわない可能性が高いものについて詳しく学んだ後で、より動的なソリューションを使用します。為に。

より具体的な例として、クライアントが「select * from people」というクエリを送信したとします。最初の部分は、clientLimitRows にクエリを実行して、特定の都市の人々や特定の年齢層の人々など、支払った金額を確認することです。このプロセスは、集計を実行して people テーブルを実際にクエリする 2 番目のプロセスの WHERE 句を作成します。次に、3 番目のプロセスが clientLimitColumns をチェックして、支払っていない列を結果から削除します。

繰り返しますが、私の意見ですが、クライアントのルールを破る必要があると思います。私がモデル化する必要があった場合、会社 A は白人、70 歳から 80 歳の間に生まれ、ブロンドの髪を持ち、家族に 1 から 2 台の車を持っている人のみにアクセスできます。「または」、黒人など..「または」混血その bla bla.. "or" )ルール (ルールごとに 1 つ)、条件 (OR セットごとに 1 つ)、および句 (AND で接続されたフィールド/演算子/値のタプルごとに 1 つ) を含むテーブルが必要です。

したがって、このルールでは、人種、年齢、髪の色、および numCars、OR レースと blah2 OR mixedRace と blah3 または blah4 で制限している場合、1 つ以上の句を含む 4 行の条件になります。

為に

rule = 1
    condition = 1
    clause1 = 'race = white'
    clause2 = 'age >= 70'
    clause3 = 'age <= 80'
    clause4 = 'haircolor = blonde'
    clause5 = 'numCars >= 1'
    clause6 = 'numCars <= 2'
    condition = 2
    clause1 = 'race = black'
    clause2 = 'field2 = blah2'
    condition = 3
    clause1 = 'race = mixedrace'
    clause2 = 'field3 = blah3'
    condition = 4
    clause1 = 'field4 = blah4'

条項テーブルにはフィールド customerID、ruleID、conditionID、clauseID、field、operator、value があります

オプション 3 で何をしているのかを 100% 理解しているとは言えませんが、クライアント マーカーを使用して people テーブルを拡張したり、人と 1 対多の関係を持つ rowID/clientID テーブルを導入したりしているようですね。次に、夜通しのプロセスで有料のルールを適用して、アクセスできる行がマークされ、結合で制限できるようにしますか? うまくいくと思いますが、今日は昨日のクエリの結果しか得られませんか? 彼らが今日新しいデータの料金を支払った場合、明日まで支払い済みとしてマークされません。本当に何かが欠けているかどうかはわかりませんが、他の誰かがより良い反応を示した場合、彼らにより多くの力が与えられます.

わかりました、あなたがどこに向かっているのかわかりました。people テーブルを clientID フィールドで拡張するテーブルを一晩作成して、各 clientID にクエリ可能な行の独自のセットを持たせたいですか? そして、あなたはその場でそれを行うことはできませんか?クエリを送信するときは、最初に行のセットを作成してから、そのセットにクエリを適用しますか?

于 2012-11-16T15:38:35.657 に答える